summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--OWNERS2
-rw-r--r--PermissionController/Android.bp9
-rw-r--r--PermissionController/AndroidManifest.xml10
-rw-r--r--PermissionController/TEST_MAPPING65
-rw-r--r--PermissionController/lint-baseline.xml216
-rw-r--r--PermissionController/proguard.flags10
-rw-r--r--PermissionController/res/drawable/ic_more_horizontal.xml26
-rw-r--r--PermissionController/res/layout-v33/action_button_list_large_screen.xml (renamed from PermissionController/res/layout-w764dp-v33/action_button_list.xml)2
-rw-r--r--PermissionController/res/layout-v33/action_button_list_small_screen.xml (renamed from PermissionController/res/layout-v33/spaced_preference_category_no_label.xml)4
-rw-r--r--PermissionController/res/layout-v33/preference_entries_top_padding.xml (renamed from PermissionController/res/layout-v33/action_button_list.xml)6
-rw-r--r--PermissionController/res/layout-v33/preference_issue_card.xml10
-rw-r--r--PermissionController/res/layout/grant_permissions.xml2
-rw-r--r--PermissionController/res/navigation-watch/nav_graph.xml126
-rw-r--r--PermissionController/res/values-af-v33/strings.xml3
-rw-r--r--PermissionController/res/values-af/strings.xml81
-rw-r--r--PermissionController/res/values-am-v33/strings.xml3
-rw-r--r--PermissionController/res/values-am/strings.xml123
-rw-r--r--PermissionController/res/values-ar-v33/strings.xml5
-rw-r--r--PermissionController/res/values-ar-v34/strings.xml2
-rw-r--r--PermissionController/res/values-ar/strings.xml87
-rw-r--r--PermissionController/res/values-as/strings.xml36
-rw-r--r--PermissionController/res/values-az-v33/strings.xml3
-rw-r--r--PermissionController/res/values-az/strings.xml65
-rw-r--r--PermissionController/res/values-b+sr+Latn-v33/strings.xml3
-rw-r--r--PermissionController/res/values-b+sr+Latn/strings.xml71
-rw-r--r--PermissionController/res/values-be-v33/strings.xml3
-rw-r--r--PermissionController/res/values-be/strings.xml79
-rw-r--r--PermissionController/res/values-bg-v33/strings.xml3
-rw-r--r--PermissionController/res/values-bg/strings.xml71
-rw-r--r--PermissionController/res/values-bn-v33/strings.xml3
-rw-r--r--PermissionController/res/values-bn/strings.xml71
-rw-r--r--PermissionController/res/values-bs-television/strings.xml2
-rw-r--r--PermissionController/res/values-bs-v33/strings.xml2
-rw-r--r--PermissionController/res/values-bs/strings.xml69
-rw-r--r--PermissionController/res/values-ca-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ca-v34/strings.xml4
-rw-r--r--PermissionController/res/values-ca/strings.xml85
-rw-r--r--PermissionController/res/values-cs-v33/strings.xml3
-rw-r--r--PermissionController/res/values-cs-v34/strings.xml4
-rw-r--r--PermissionController/res/values-cs/strings.xml73
-rw-r--r--PermissionController/res/values-da-v33/strings.xml3
-rw-r--r--PermissionController/res/values-da/strings.xml75
-rw-r--r--PermissionController/res/values-de-v33/strings.xml3
-rw-r--r--PermissionController/res/values-de-v34/strings.xml3
-rw-r--r--PermissionController/res/values-de/strings.xml73
-rw-r--r--PermissionController/res/values-el-v33/strings.xml5
-rw-r--r--PermissionController/res/values-el/strings.xml127
-rw-r--r--PermissionController/res/values-en-rAU/strings.xml34
-rw-r--r--PermissionController/res/values-en-rCA/strings.xml30
-rw-r--r--PermissionController/res/values-en-rGB/strings.xml34
-rw-r--r--PermissionController/res/values-en-rIN/strings.xml34
-rw-r--r--PermissionController/res/values-en-rXC/strings.xml30
-rw-r--r--PermissionController/res/values-es-rUS-v33/strings.xml3
-rw-r--r--PermissionController/res/values-es-rUS/strings.xml75
-rw-r--r--PermissionController/res/values-es-v33/strings.xml3
-rw-r--r--PermissionController/res/values-es/strings.xml77
-rw-r--r--PermissionController/res/values-et-v34/strings.xml2
-rw-r--r--PermissionController/res/values-et/strings.xml67
-rw-r--r--PermissionController/res/values-eu-v33/strings.xml3
-rw-r--r--PermissionController/res/values-eu/strings.xml83
-rw-r--r--PermissionController/res/values-fa-v33/strings.xml3
-rw-r--r--PermissionController/res/values-fa/strings.xml62
-rw-r--r--PermissionController/res/values-fi-v33/strings.xml3
-rw-r--r--PermissionController/res/values-fi-v34/strings.xml2
-rw-r--r--PermissionController/res/values-fi/strings.xml73
-rw-r--r--PermissionController/res/values-fr-rCA-v33/strings.xml5
-rw-r--r--PermissionController/res/values-fr-rCA-v34/strings.xml2
-rw-r--r--PermissionController/res/values-fr-rCA/strings.xml75
-rw-r--r--PermissionController/res/values-fr-v33/strings.xml3
-rw-r--r--PermissionController/res/values-fr-v34/strings.xml2
-rw-r--r--PermissionController/res/values-fr/strings.xml91
-rw-r--r--PermissionController/res/values-gl-v33/strings.xml3
-rw-r--r--PermissionController/res/values-gl/strings.xml71
-rw-r--r--PermissionController/res/values-gu-v33/strings.xml3
-rw-r--r--PermissionController/res/values-gu/strings.xml77
-rw-r--r--PermissionController/res/values-hi/strings.xml83
-rw-r--r--PermissionController/res/values-hr-v33/strings.xml5
-rw-r--r--PermissionController/res/values-hr-v34/strings.xml2
-rw-r--r--PermissionController/res/values-hr/strings.xml103
-rw-r--r--PermissionController/res/values-hu-v33/strings.xml3
-rw-r--r--PermissionController/res/values-hu/strings.xml69
-rw-r--r--PermissionController/res/values-hy-v33/strings.xml3
-rw-r--r--PermissionController/res/values-hy/strings.xml69
-rw-r--r--PermissionController/res/values-in-v33/strings.xml5
-rw-r--r--PermissionController/res/values-in-v34/strings.xml2
-rw-r--r--PermissionController/res/values-in/strings.xml89
-rw-r--r--PermissionController/res/values-is-v33/strings.xml3
-rw-r--r--PermissionController/res/values-is/strings.xml69
-rw-r--r--PermissionController/res/values-it/strings.xml71
-rw-r--r--PermissionController/res/values-iw-v33/strings.xml3
-rw-r--r--PermissionController/res/values-iw/strings.xml71
-rw-r--r--PermissionController/res/values-ja-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ja/strings.xml87
-rw-r--r--PermissionController/res/values-ka-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ka/strings.xml40
-rw-r--r--PermissionController/res/values-kk-v33/strings.xml7
-rw-r--r--PermissionController/res/values-kk-v34/strings.xml2
-rw-r--r--PermissionController/res/values-kk/strings.xml89
-rw-r--r--PermissionController/res/values-km/strings.xml61
-rw-r--r--PermissionController/res/values-kn-v33/strings.xml3
-rw-r--r--PermissionController/res/values-kn/strings.xml111
-rw-r--r--PermissionController/res/values-ko-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ko-v34/strings.xml2
-rw-r--r--PermissionController/res/values-ko/strings.xml73
-rw-r--r--PermissionController/res/values-ky-television/strings.xml2
-rw-r--r--PermissionController/res/values-ky-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ky-v34/strings.xml4
-rw-r--r--PermissionController/res/values-ky-watch/strings.xml2
-rw-r--r--PermissionController/res/values-ky/strings.xml87
-rw-r--r--PermissionController/res/values-lo-v33/strings.xml3
-rw-r--r--PermissionController/res/values-lo/strings.xml63
-rw-r--r--PermissionController/res/values-lt-v33/strings.xml3
-rw-r--r--PermissionController/res/values-lt/strings.xml65
-rw-r--r--PermissionController/res/values-lv-v33/strings.xml3
-rw-r--r--PermissionController/res/values-lv/strings.xml63
-rw-r--r--PermissionController/res/values-mk-v33/strings.xml5
-rw-r--r--PermissionController/res/values-mk-v34/strings.xml4
-rw-r--r--PermissionController/res/values-mk/strings.xml81
-rw-r--r--PermissionController/res/values-ml/strings.xml30
-rw-r--r--PermissionController/res/values-mn-v33/strings.xml3
-rw-r--r--PermissionController/res/values-mn/strings.xml69
-rw-r--r--PermissionController/res/values-mr-v33/strings.xml3
-rw-r--r--PermissionController/res/values-mr-v34/strings.xml2
-rw-r--r--PermissionController/res/values-mr/strings.xml73
-rw-r--r--PermissionController/res/values-ms-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ms/strings.xml36
-rw-r--r--PermissionController/res/values-my-v33/strings.xml3
-rw-r--r--PermissionController/res/values-my/strings.xml77
-rw-r--r--PermissionController/res/values-nb-v33/strings.xml3
-rw-r--r--PermissionController/res/values-nb/strings.xml69
-rw-r--r--PermissionController/res/values-ne-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ne/strings.xml73
-rw-r--r--PermissionController/res/values-night-v33/themes.xml12
-rw-r--r--PermissionController/res/values-night-v34/themes.xml5
-rw-r--r--PermissionController/res/values-nl-v33/strings.xml3
-rw-r--r--PermissionController/res/values-nl-v34/strings.xml2
-rw-r--r--PermissionController/res/values-nl/strings.xml77
-rw-r--r--PermissionController/res/values-or-v33/strings.xml3
-rw-r--r--PermissionController/res/values-or-v34/strings.xml2
-rw-r--r--PermissionController/res/values-or-watch/strings.xml2
-rw-r--r--PermissionController/res/values-or/strings.xml84
-rw-r--r--PermissionController/res/values-pa-v33/strings.xml5
-rw-r--r--PermissionController/res/values-pa/strings.xml73
-rw-r--r--PermissionController/res/values-pl-v33/strings.xml3
-rw-r--r--PermissionController/res/values-pl-v34/strings.xml4
-rw-r--r--PermissionController/res/values-pl/strings.xml81
-rw-r--r--PermissionController/res/values-pt-rBR-v33/strings.xml2
-rw-r--r--PermissionController/res/values-pt-rBR/strings.xml77
-rw-r--r--PermissionController/res/values-pt-rPT-v33/strings.xml3
-rw-r--r--PermissionController/res/values-pt-rPT/strings.xml107
-rw-r--r--PermissionController/res/values-pt-v33/strings.xml2
-rw-r--r--PermissionController/res/values-pt/strings.xml77
-rw-r--r--PermissionController/res/values-ro-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ro/strings.xml69
-rw-r--r--PermissionController/res/values-ru-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ru-v34/strings.xml2
-rw-r--r--PermissionController/res/values-ru/strings.xml83
-rw-r--r--PermissionController/res/values-si-v33/strings.xml3
-rw-r--r--PermissionController/res/values-si/strings.xml65
-rw-r--r--PermissionController/res/values-sk/strings.xml61
-rw-r--r--PermissionController/res/values-sl-v33/strings.xml4
-rw-r--r--PermissionController/res/values-sl-v34/strings.xml4
-rw-r--r--PermissionController/res/values-sl/strings.xml40
-rw-r--r--PermissionController/res/values-sq-v33/strings.xml3
-rw-r--r--PermissionController/res/values-sq/strings.xml81
-rw-r--r--PermissionController/res/values-sr-v33/strings.xml3
-rw-r--r--PermissionController/res/values-sr/strings.xml71
-rw-r--r--PermissionController/res/values-sv-v33/strings.xml3
-rw-r--r--PermissionController/res/values-sv-v34/strings.xml2
-rw-r--r--PermissionController/res/values-sv/strings.xml67
-rw-r--r--PermissionController/res/values-sw-v33/strings.xml5
-rw-r--r--PermissionController/res/values-sw-v34/strings.xml4
-rw-r--r--PermissionController/res/values-sw/strings.xml73
-rw-r--r--PermissionController/res/values-ta-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ta/strings.xml65
-rw-r--r--PermissionController/res/values-te/strings.xml71
-rw-r--r--PermissionController/res/values-th-v33/strings.xml3
-rw-r--r--PermissionController/res/values-th-v34/strings.xml2
-rw-r--r--PermissionController/res/values-th/strings.xml71
-rw-r--r--PermissionController/res/values-tl-v33/strings.xml3
-rw-r--r--PermissionController/res/values-tl/strings.xml42
-rw-r--r--PermissionController/res/values-tr-v33/strings.xml3
-rw-r--r--PermissionController/res/values-tr/strings.xml71
-rw-r--r--PermissionController/res/values-uk-v33/strings.xml3
-rw-r--r--PermissionController/res/values-uk-v34/strings.xml6
-rw-r--r--PermissionController/res/values-uk/strings.xml73
-rw-r--r--PermissionController/res/values-ur-v33/strings.xml3
-rw-r--r--PermissionController/res/values-ur/strings.xml75
-rw-r--r--PermissionController/res/values-uz-v33/strings.xml3
-rw-r--r--PermissionController/res/values-uz/strings.xml77
-rw-r--r--PermissionController/res/values-v31/styles.xml8
-rw-r--r--PermissionController/res/values-v33/attrs.xml3
-rw-r--r--PermissionController/res/values-v33/dimens.xml9
-rw-r--r--PermissionController/res/values-v33/layout.xml9
-rw-r--r--PermissionController/res/values-v33/styles.xml24
-rw-r--r--PermissionController/res/values-v33/themes.xml24
-rw-r--r--PermissionController/res/values-v34/strings.xml2
-rw-r--r--PermissionController/res/values-v35/bools.xml21
-rw-r--r--PermissionController/res/values-vi-v33/strings.xml3
-rw-r--r--PermissionController/res/values-vi-v34/strings.xml4
-rw-r--r--PermissionController/res/values-vi/strings.xml91
-rw-r--r--PermissionController/res/values-w764dp-v33/layout.xml6
-rw-r--r--PermissionController/res/values-w764dp-v33/styles.xml14
-rw-r--r--PermissionController/res/values-watch/themes.xml4
-rw-r--r--PermissionController/res/values-zh-rCN-v33/strings.xml3
-rw-r--r--PermissionController/res/values-zh-rCN/strings.xml103
-rw-r--r--PermissionController/res/values-zh-rHK-car/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rHK-television/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rHK-v33/strings.xml6
-rw-r--r--PermissionController/res/values-zh-rHK-v34/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rHK/strings.xml233
-rw-r--r--PermissionController/res/values-zh-rTW-v34/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rTW/strings.xml65
-rw-r--r--PermissionController/res/values-zu-v33/strings.xml3
-rw-r--r--PermissionController/res/values-zu/strings.xml71
-rw-r--r--PermissionController/res/values/bools.xml1
-rw-r--r--PermissionController/res/values/colors.xml3
-rw-r--r--PermissionController/res/values/overlayable.xml36
-rw-r--r--PermissionController/res/values/strings.xml80
-rw-r--r--PermissionController/res/values/styles.xml12
-rw-r--r--PermissionController/res/values/themes.xml2
-rw-r--r--PermissionController/res/xml/roles.xml28
-rw-r--r--PermissionController/res/xml/safety_center_dashboard.xml7
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java110
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java49
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java63
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java59
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Permission.java6
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java19
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java14
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java41
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java14
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java13
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Role.java6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/Constants.java11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/AutoSettingsFrameFragment.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/TEST_MAPPING3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/ConfirmationActivity.java40
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/PendingList.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/wear/ConfirmationActivityWearViewHandler.java85
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationActivityViewModel.kt59
-rw-r--r--PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt86
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING70
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java84
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/LocationAccessCheck.java59
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt63
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/TEST_MAPPING55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java145
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/ManagePermissionsActivity.java52
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/TEST_MAPPING15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/GrantPermissionsAutoViewHandler.java12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java53
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ReviewPermissionsFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt81
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/NewGrantPermissionsViewModel.kt1300
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BackgroundGrantBehavior.kt207
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BasicGrantBehavior.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/GrantBehavior.kt85
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/HealthGrantBehavior.kt53
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/LocationGrantBehavior.kt106
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/NotificationGrantBehavior.kt58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/StorageGrantBehavior.kt135
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/AppPermissionsFragmentWear.java407
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/GrantPermissionsWearViewHandler.java389
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/ReviewPermissionsWearFragment.java4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt340
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt113
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt337
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt133
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt223
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt147
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt75
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt61
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt159
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt73
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt124
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt205
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt153
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt307
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt112
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt30
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt202
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Button.kt137
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt266
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt172
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Icon.kt139
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListFooter.kt88
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt154
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt168
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt200
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChipToggleControl.kt21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionConfirmDialogViewModel.kt60
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionGroupsRevokeDialogViewModel.kt53
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearGrantPermissionsViewModel.kt65
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearUnusedAppsViewModel.kt60
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/ContextCompat.java70
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt917
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java305
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt67
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerPregrants.kt42
-rw-r--r--PermissionController/src/com/android/permissioncontroller/privacysources/TEST_MAPPING16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING21
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListActivity.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt113
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt119
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListFragment.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt68
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt84
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt122
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt61
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/model/DefaultAppConfirmDialogViewModel.kt55
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java29
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterJobServiceFlags.java13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardPreference.java23
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java48
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java29
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterSubpageFragment.kt11
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/LazyProperties.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/MoreIssuesHeaderView.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryCommonViewsManager.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt24
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryView.kt4
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetylabel/TEST_MAPPING29
-rw-r--r--PermissionController/tests/inprocess/Android.bp5
-rw-r--r--PermissionController/tests/inprocess/AndroidTest.xml6
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java258
-rw-r--r--PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt2
-rw-r--r--PermissionController/tests/mocking/Android.bp5
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt67
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt48
-rw-r--r--PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt9
-rw-r--r--PermissionController/tests/permissionui/Android.bp2
-rw-r--r--PermissionController/tests/permissionui/AndroidTest.xml20
-rw-r--r--PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/Android.bp34
-rw-r--r--PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/AndroidManifest.xml26
-rw-r--r--PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt21
-rw-r--r--PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/Android.bp34
-rw-r--r--PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/AndroidManifest.xml34
-rw-r--r--PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt21
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt35
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt6
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt3
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt4
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt140
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt112
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt2
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt92
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt2
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt13
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt4
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt181
-rw-r--r--PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt9
-rw-r--r--SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java40
-rw-r--r--SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresVanillaIceCreamByDefault.java40
-rw-r--r--SafetyCenter/Config/TEST_MAPPING2
-rw-r--r--SafetyCenter/ConfigLintChecker/java/android/os/Build.java4
-rw-r--r--SafetyCenter/ConfigLintChecker/java/com/android/modules/utils/build/SdkLevel.java6
-rw-r--r--SafetyCenter/Resources/res/raw-v35/safety_center_config.xml136
-rw-r--r--SafetyCenter/Resources/res/values-af-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-af-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-af/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-am-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-am-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-am/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ar-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ar-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ar/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-as-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-as-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-az-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-az-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-b+sr+Latn-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-be-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-be-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-be/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-bg-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-bg-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-bn-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-bn-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-bs-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-bs-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ca-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ca-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ca/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-cs-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-cs-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-da-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-da-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-da/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-de-v34/strings.xml10
-rw-r--r--SafetyCenter/Resources/res/values-de-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-el-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-el-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-en-rAU-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-en-rCA-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-en-rGB-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-en-rIN-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-en-rXC-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-es-rUS-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-es-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-es-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-et-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-et-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-eu-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-eu-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-fa-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-fa-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-fi-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-fi-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-fr-rCA-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-fr-rCA/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-fr-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-fr-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-gl-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-gl-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-gu-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-gu-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-hi-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-hi-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-hr-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-hr-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-hr/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-hu-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-hu-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-hy-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-hy-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-in-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-in-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-in/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-is-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-is-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-it-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-it-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-it/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-iw-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-iw-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ja-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ja-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ka-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ka-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-kk-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-kk-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-kk/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-km-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-km-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-km/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-kn-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-kn-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ko-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ko-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ky-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-ky-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-lo-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-lo-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-lt-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-lt-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-lv-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-lv-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-mk-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-mk-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-mk/strings.xml8
-rw-r--r--SafetyCenter/Resources/res/values-ml-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ml-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-mn-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-mn-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-mr-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-mr-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ms-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-ms-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-my-v34/strings.xml8
-rw-r--r--SafetyCenter/Resources/res/values-my-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-nb-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-nb-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ne-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ne-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ne/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-nl-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-nl-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-nl/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-or-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-or-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-or/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-pa-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-pa-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-pl-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-pl-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-pt-rBR-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-pt-rPT-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-pt-rPT/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-pt-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-pt-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ro-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ro-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ru-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-ru-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ru/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-si-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-si-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sk-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sk-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sl-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sl-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sq-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sq-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sr-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sr-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sr/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-sv-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sv-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-sw-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-sw-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-ta-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ta-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-te-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-te-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-te/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-th-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-th-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-tl-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-tl-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-tr-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-tr-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-uk-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-uk-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-uk/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ur-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ur-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-uz-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-uz-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-uz/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-v34/config.xml2
-rw-r--r--SafetyCenter/Resources/res/values-v35/config.xml23
-rw-r--r--SafetyCenter/Resources/res/values-v35/strings.xml24
-rw-r--r--SafetyCenter/Resources/res/values-vi-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-vi-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-vi/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-zh-rCN-v34/strings.xml6
-rw-r--r--SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-zh-rHK-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-zh-rTW-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values-zu-v34/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-zu-v35/strings.xml23
-rw-r--r--SafetyCenter/Resources/res/values/config.xml2
-rw-r--r--SafetyCenter/Resources/shared_res/values-af/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-am/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ar/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-as/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-az/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-b+sr+Latn/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-be/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-bg/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-bn/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-bs/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ca/strings.xml13
-rw-r--r--SafetyCenter/Resources/shared_res/values-cs/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-da/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-de/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-el/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-en-rAU/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-en-rCA/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-en-rGB/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-en-rIN/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-en-rXC/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-es-rUS/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-es/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-et/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-eu/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-fa/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-fi/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-fr-rCA/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-fr/strings.xml15
-rw-r--r--SafetyCenter/Resources/shared_res/values-gl/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-gu/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-hi/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-hr/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-hu/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-hy/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-in/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-is/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-it/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-iw/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ja/strings.xml15
-rw-r--r--SafetyCenter/Resources/shared_res/values-ka/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-kk/strings.xml13
-rw-r--r--SafetyCenter/Resources/shared_res/values-km/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-kn/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-ko/strings.xml13
-rw-r--r--SafetyCenter/Resources/shared_res/values-ky/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-lo/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-lt/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-lv/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-mk/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-ml/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-mn/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-mr/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ms/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-my/strings.xml15
-rw-r--r--SafetyCenter/Resources/shared_res/values-nb/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ne/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-nl/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-or/strings.xml13
-rw-r--r--SafetyCenter/Resources/shared_res/values-pa/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-pl/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-pt-rBR/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-pt-rPT/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-pt/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-ro/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ru/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-si/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-sk/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-sl/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-sq/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-sr/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-sv/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-sw/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ta/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-te/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-th/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-tl/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-tr/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-uk/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-ur/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-uz/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-vi/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values-zh-rCN/strings.xml11
-rw-r--r--SafetyCenter/Resources/shared_res/values-zh-rHK/strings.xml19
-rw-r--r--SafetyCenter/Resources/shared_res/values-zh-rTW/strings.xml13
-rw-r--r--SafetyCenter/Resources/shared_res/values-zu/strings.xml9
-rw-r--r--SafetyCenter/Resources/shared_res/values/strings.xml3
-rw-r--r--SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesApk.java353
-rw-r--r--SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java403
-rw-r--r--SafetyCenter/ResourcesLib/tests/AndroidTest.xml2
-rw-r--r--SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt1
-rw-r--r--SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesApkTest.kt440
-rw-r--r--SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt226
-rw-r--r--SafetyCenter/TEST_MAPPING6
-rw-r--r--TEST_MAPPING62
-rw-r--r--flags/Android.bp65
-rw-r--r--flags/flags.aconfig8
-rw-r--r--flags/java/com/android/permission/flags/PermissionsFlags.java20
-rw-r--r--framework-s/java/android/app/role/RoleManager.java12
-rw-r--r--framework-s/java/android/app/role/TEST_MAPPING19
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenter.md3
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterData.java12
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterIssue.java17
-rw-r--r--framework-s/java/android/safetycenter/SafetyCenterManager.java2
-rw-r--r--framework-s/java/android/safetycenter/SafetyEvent.java3
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceData.java14
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceIssue.java42
-rw-r--r--framework-s/java/android/safetycenter/SafetySourceStatus.java3
-rw-r--r--framework-s/java/android/safetycenter/config/SafetyCenterConfig.java3
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySource.java24
-rw-r--r--framework-s/java/android/safetycenter/config/SafetySourcesGroup.java3
-rw-r--r--permissions/Android.bp6
-rw-r--r--service/java/com/android/role/RoleService.java60
-rw-r--r--service/java/com/android/role/TEST_MAPPING27
-rw-r--r--service/java/com/android/safetycenter/ApiLock.java5
-rw-r--r--service/java/com/android/safetycenter/DevicePolicyResources.java22
-rw-r--r--service/java/com/android/safetycenter/PendingIntentFactory.java20
-rw-r--r--service/java/com/android/safetycenter/RefreshReasons.java11
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterBroadcastDispatcher.java68
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterConfigReader.java57
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataChangeNotifier.java5
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterDataFactory.java117
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterFlags.java36
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterListeners.java18
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java92
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterService.java440
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterShellCommandHandler.java14
-rw-r--r--service/java/com/android/safetycenter/SafetyCenterTimeouts.java5
-rw-r--r--service/java/com/android/safetycenter/SafetySourceIssueInfo.java6
-rw-r--r--service/java/com/android/safetycenter/SafetySourceIssues.java87
-rw-r--r--service/java/com/android/safetycenter/SafetySourceKey.java6
-rw-r--r--service/java/com/android/safetycenter/SafetySources.java5
-rw-r--r--service/java/com/android/safetycenter/SafetySourcesGroups.java5
-rw-r--r--service/java/com/android/safetycenter/UserProfileGroup.java17
-rw-r--r--service/java/com/android/safetycenter/data/AndroidLockScreenFix.java26
-rw-r--r--service/java/com/android/safetycenter/data/SafetyCenterDataManager.java93
-rw-r--r--service/java/com/android/safetycenter/data/SafetyCenterInFlightIssueActionRepository.java36
-rw-r--r--service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java12
-rw-r--r--service/java/com/android/safetycenter/data/SafetyCenterIssueDismissalRepository.java32
-rw-r--r--service/java/com/android/safetycenter/data/SafetyCenterIssueRepository.java18
-rw-r--r--service/java/com/android/safetycenter/data/SafetyEventFix.java118
-rw-r--r--service/java/com/android/safetycenter/data/SafetySourceDataRepository.java68
-rw-r--r--service/java/com/android/safetycenter/data/SafetySourceDataValidator.java44
-rw-r--r--service/java/com/android/safetycenter/data/SafetySourceStateCollectedLogger.java9
-rw-r--r--service/java/com/android/safetycenter/data/package-info.java2
-rw-r--r--service/java/com/android/safetycenter/logging/SafetyCenterPullAtomCallback.java18
-rw-r--r--service/java/com/android/safetycenter/logging/SafetyCenterStatsdLogger.java6
-rw-r--r--service/java/com/android/safetycenter/logging/package-info.java2
-rw-r--r--service/java/com/android/safetycenter/notifications/SafetyCenterNotificationChannels.java92
-rw-r--r--service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java46
-rw-r--r--service/java/com/android/safetycenter/notifications/SafetyCenterNotificationReceiver.java39
-rw-r--r--service/java/com/android/safetycenter/notifications/SafetyCenterNotificationSender.java39
-rw-r--r--service/java/com/android/safetycenter/notifications/package-info.java2
-rw-r--r--service/java/com/android/safetycenter/package-info.java2
-rw-r--r--service/lint-baseline.xml18
-rw-r--r--tests/cts/permission/Android.bp127
-rw-r--r--tests/cts/permission/AndroidManifest.xml100
-rw-r--r--tests/cts/permission/AndroidTest.xml137
-rw-r--r--tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/Android.bp35
-rw-r--r--tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/AndroidManifest.xml40
-rw-r--r--tests/cts/permission/AppThatAccessesLocationOnCommand/Android.bp40
-rw-r--r--tests/cts/permission/AppThatAccessesLocationOnCommand/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/AccessLocationOnCommand.java68
-rw-r--r--tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl22
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionA/Android.bp32
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionA/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/Android.bp32
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/Android.bp32
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/Android.bp32
-rw-r--r--tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionA/Android.bp32
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionA/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/Android.bp31
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/Android.bp31
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/Android.bp31
-rw-r--r--tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/Android.bp32
-rw-r--r--tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml38
-rw-r--r--tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/src/android/permission/cts/appthatrequestpermission/RequestPermissions.kt49
-rw-r--r--tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/Android.bp36
-rw-r--r--tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/AndroidManifest.xml24
-rw-r--r--tests/cts/permission/AppThatHasNotificationListener/Android.bp39
-rw-r--r--tests/cts/permission/AppThatHasNotificationListener/AndroidManifest.xml33
-rw-r--r--tests/cts/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java21
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermission30/Android.bp40
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermission30/AndroidManifest.xml35
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java161
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermission31/Android.bp33
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermission31/AndroidManifest.xml34
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/Android.bp33
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/AndroidManifest.xml40
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml36
-rw-r--r--tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/AndroidManifest.xml29
-rw-r--r--tests/cts/permission/AppThatRequestContactsPermission15/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestContactsPermission15/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestContactsPermission16/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestContactsPermission16/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestCustomCameraPermission/Android.bp37
-rw-r--r--tests/cts/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml40
-rw-r--r--tests/cts/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml20
-rw-r--r--tests/cts/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java85
-rw-r--r--tests/cts/permission/AppThatRequestDevicePermissions/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestDevicePermissions/AndroidManifest.xml41
-rw-r--r--tests/cts/permission/AppThatRequestDevicePermissions/src/android/permission/cts/appthatrequestpermission/RevokeSelfPermissionReceiver.kt41
-rw-r--r--tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/AndroidManifest.xml32
-rw-r--r--tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/Android.bp33
-rw-r--r--tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission22/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission22/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission28/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission28/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission29/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission29/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission29v4/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestLocationPermission29v4/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/AndroidManifest.xml30
-rw-r--r--tests/cts/permission/AppThatRequestOneTimePermission/Android.bp35
-rw-r--r--tests/cts/permission/AppThatRequestOneTimePermission/AndroidManifest.xml36
-rw-r--r--tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/KeepAliveForegroundService.java72
-rw-r--r--tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/RequestPermission.java29
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandB/Android.bp33
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandB/AndroidManifest.xml35
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandB/res/values/strings.xml19
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandB/src/android/permission/cts/appthatrequestpermission/RequestPermission.java30
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandC/Android.bp33
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandC/AndroidManifest.xml35
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandC/res/values/strings.xml19
-rw-r--r--tests/cts/permission/AppThatRequestPermissionAandC/src/android/permission/cts/appthatrequestpermission/RequestPermission.java30
-rw-r--r--tests/cts/permission/AppThatRequestStoragePermission28/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestStoragePermission28/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestStoragePermission29/Android.bp31
-rw-r--r--tests/cts/permission/AppThatRequestStoragePermission29/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/AppThatRequestSystemAlertWindow22/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml24
-rw-r--r--tests/cts/permission/AppThatRequestSystemAlertWindow23/Android.bp32
-rw-r--r--tests/cts/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml24
-rw-r--r--tests/cts/permission/AppThatRunsRationaleTests/Android.bp35
-rw-r--r--tests/cts/permission/AppThatRunsRationaleTests/AndroidManifest.xml26
-rw-r--r--tests/cts/permission/AppThatRunsRationaleTests/src/android/permission/cts/appthatrunsrationaletests/TestActivity.java42
-rw-r--r--tests/cts/permission/AppToTestRevokeSelfPermission/Android.bp35
-rw-r--r--tests/cts/permission/AppToTestRevokeSelfPermission/AndroidManifest.xml31
-rw-r--r--tests/cts/permission/AppToTestRevokeSelfPermission/src/android/permission/cts/apptotestselfrevokepermission/RevokePermission.java49
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/Android.bp33
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/AndroidManifest.xml29
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/Android.bp33
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/AndroidManifest.xml30
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/Android.bp30
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/AndroidManifest.xml24
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestsPermissions/Android.bp30
-rw-r--r--tests/cts/permission/AppWithSharedUidThatRequestsPermissions/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/OWNERS12
-rw-r--r--tests/cts/permission/README16
-rw-r--r--tests/cts/permission/StorageEscalationApp28/Android.bp30
-rw-r--r--tests/cts/permission/StorageEscalationApp28/AndroidManifest.xml30
-rw-r--r--tests/cts/permission/StorageEscalationApp29Full/Android.bp30
-rw-r--r--tests/cts/permission/StorageEscalationApp29Full/AndroidManifest.xml30
-rw-r--r--tests/cts/permission/StorageEscalationApp29Scoped/Android.bp30
-rw-r--r--tests/cts/permission/StorageEscalationApp29Scoped/AndroidManifest.xml30
-rw-r--r--tests/cts/permission/jni/Android.bp60
-rw-r--r--tests/cts/permission/jni/CtsPermissionsJniOnLoad.cpp34
-rw-r--r--tests/cts/permission/jni/PermissionManagerNativeJniTest.cpp50
-rw-r--r--tests/cts/permission/jni/android_permission_cts_FileUtils.cpp250
-rw-r--r--tests/cts/permission/nativeTests/Android.bp56
-rw-r--r--tests/cts/permission/nativeTests/AndroidTest.xml43
-rw-r--r--tests/cts/permission/nativeTests/src/PermissionManagerNativeTest.cpp63
-rw-r--r--tests/cts/permission/permissionTestUtilLib/Android.bp37
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerHelperRule.kt58
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerService.java72
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerServiceUtils.kt119
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/MtsIgnore.java40
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/PermissionUtils.java414
-rw-r--r--tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java205
-rw-r--r--tests/cts/permission/res/drawable/robot.pngbin0 -> 5634 bytes
-rw-r--r--tests/cts/permission/res/values/strings.xml22
-rw-r--r--tests/cts/permission/res/xml/test_accessibilityservice.xml21
-rw-r--r--tests/cts/permission/sdk28/Android.bp33
-rw-r--r--tests/cts/permission/sdk28/AndroidManifest.xml52
-rw-r--r--tests/cts/permission/sdk28/AndroidTest.xml32
-rw-r--r--tests/cts/permission/sdk28/OWNERS1
-rw-r--r--tests/cts/permission/sdk28/TEST_MAPPING7
-rw-r--r--tests/cts/permission/sdk28/res/values/strings.xml19
-rw-r--r--tests/cts/permission/sdk28/src/android/permission/cts/sdk28/RequestLocation.java70
-rw-r--r--tests/cts/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt358
-rw-r--r--tests/cts/permission/src/android/permission/cts/AccessibilityTestService.kt24
-rw-r--r--tests/cts/permission/src/android/permission/cts/ActivityPermissionRationaleTest.java135
-rw-r--r--tests/cts/permission/src/android/permission/cts/AppIdleStatePermissionTest.java92
-rw-r--r--tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java61
-rw-r--r--tests/cts/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java55
-rw-r--r--tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java254
-rw-r--r--tests/cts/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java324
-rw-r--r--tests/cts/permission/src/android/permission/cts/Camera2PermissionTest.java191
-rw-r--r--tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java94
-rw-r--r--tests/cts/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java120
-rw-r--r--tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java157
-rw-r--r--tests/cts/permission/src/android/permission/cts/DebuggableTest.java50
-rw-r--r--tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt221
-rw-r--r--tests/cts/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt190
-rw-r--r--tests/cts/permission/src/android/permission/cts/EthernetManagerPermissionTest.java113
-rw-r--r--tests/cts/permission/src/android/permission/cts/FileSystemPermissionTest.java1279
-rw-r--r--tests/cts/permission/src/android/permission/cts/FileUtils.java128
-rw-r--r--tests/cts/permission/src/android/permission/cts/IgnoreAllTestsRule.java52
-rw-r--r--tests/cts/permission/src/android/permission/cts/LocationAccessCheckTest.java851
-rw-r--r--tests/cts/permission/src/android/permission/cts/MainlineNetworkStackPermissionTest.java68
-rw-r--r--tests/cts/permission/src/android/permission/cts/MinMaxSdkVersionTest.kt96
-rw-r--r--tests/cts/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java307
-rw-r--r--tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java275
-rw-r--r--tests/cts/permission/src/android/permission/cts/NfcPermissionTest.java221
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java98
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java123
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java103
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java105
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java99
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java98
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java103
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoRollbackPermissionTest.java48
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java170
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java118
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java189
-rw-r--r--tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java219
-rw-r--r--tests/cts/permission/src/android/permission/cts/NotificationListenerCheckTest.java226
-rw-r--r--tests/cts/permission/src/android/permission/cts/NotificationListenerCheckWithSafetyCenterUnsupportedTest.java108
-rw-r--r--tests/cts/permission/src/android/permission/cts/OneTimePermissionTest.java395
-rw-r--r--tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java123
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionControllerTest.java517
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionFlagsTest.java254
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionGroupChange.java207
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionManagerNativeJniTest.java26
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionManagerTest.java52
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionStubActivity.java46
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java129
-rw-r--r--tests/cts/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt56
-rw-r--r--tests/cts/permission/src/android/permission/cts/PowerManagerServicePermissionTest.java57
-rw-r--r--tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java295
-rw-r--r--tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java48
-rw-r--r--tests/cts/permission/src/android/permission/cts/RemovePermissionTest.java247
-rw-r--r--tests/cts/permission/src/android/permission/cts/RevokePermissionTest.kt198
-rw-r--r--tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt63
-rw-r--r--tests/cts/permission/src/android/permission/cts/RevokeSelfPermissionTest.java361
-rw-r--r--tests/cts/permission/src/android/permission/cts/RuntimePermissionPresentationInfoTest.java64
-rw-r--r--tests/cts/permission/src/android/permission/cts/SafetyCenterUtils.kt151
-rw-r--r--tests/cts/permission/src/android/permission/cts/SdkSandboxPermissionTest.java64
-rw-r--r--tests/cts/permission/src/android/permission/cts/SecureElementPermissionTest.java66
-rw-r--r--tests/cts/permission/src/android/permission/cts/ServicePermissionTest.java75
-rw-r--r--tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java92
-rw-r--r--tests/cts/permission/src/android/permission/cts/SharedUidPermissionsTest.java150
-rw-r--r--tests/cts/permission/src/android/permission/cts/ShellCommandPermissionTest.java61
-rw-r--r--tests/cts/permission/src/android/permission/cts/ShellPermissionTest.java95
-rw-r--r--tests/cts/permission/src/android/permission/cts/SmsManagerPermissionTest.java124
-rw-r--r--tests/cts/permission/src/android/permission/cts/SplitPermissionTest.java584
-rwxr-xr-xtests/cts/permission/src/android/permission/cts/SplitPermissionsSystemTest.java174
-rw-r--r--tests/cts/permission/src/android/permission/cts/StorageEscalationTest.kt152
-rw-r--r--tests/cts/permission/src/android/permission/cts/TvPermissionTest.java116
-rw-r--r--tests/cts/permission/src/android/permission/cts/UndefinedGroupPermissionTest.kt204
-rw-r--r--tests/cts/permission/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl22
-rw-r--r--tests/cts/permission/telephony/Android.bp38
-rw-r--r--tests/cts/permission/telephony/AndroidManifest.xml37
-rw-r--r--tests/cts/permission/telephony/AndroidTest.xml44
-rw-r--r--tests/cts/permission/telephony/OWNERS3
-rw-r--r--tests/cts/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java470
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/res/values/strings.xml19
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/AndroidManifest.xml27
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstalltimePermissionUserApp/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/AndroidManifest.xml28
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/res/values/strings.xml19
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/Android.bp32
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/AndroidManifest.xml25
-rw-r--r--tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/res/values/strings.xml19
-rw-r--r--tests/cts/permissionmultiuser/Android.bp47
-rw-r--r--tests/cts/permissionmultiuser/AndroidManifest.xml34
-rw-r--r--tests/cts/permissionmultiuser/AndroidTest.xml71
-rw-r--r--tests/cts/permissionmultiuser/OWNERS3
-rw-r--r--tests/cts/permissionmultiuser/RequestLocationApp/Android.bp25
-rw-r--r--tests/cts/permissionmultiuser/RequestLocationApp/AndroidManifest.xml23
-rw-r--r--tests/cts/permissionmultiuser/TEST_MAPPING7
-rw-r--r--tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt476
-rw-r--r--tests/cts/permissionpolicy/Android.bp66
-rwxr-xr-xtests/cts/permissionpolicy/AndroidManifest.xml74
-rw-r--r--tests/cts/permissionpolicy/AndroidTest.xml84
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/AndroidManifest.xml26
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/AndroidManifest.xml26
-rw-r--r--tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/Android.bp30
-rw-r--r--tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/AndroidManifest.xml29
-rw-r--r--tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/Android.bp30
-rw-r--r--tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionpolicy/CtsProcessOutgoingCalls/Android.bp33
-rw-r--r--tests/cts/permissionpolicy/CtsProcessOutgoingCalls/AndroidManifest.xml33
-rw-r--r--tests/cts/permissionpolicy/CtsProcessOutgoingCalls/src/android/permissionpolicy/cts/receivecallbroadcast/ProcessOutgoingCallReceiver.kt35
-rw-r--r--tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/Android.bp30
-rw-r--r--tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/AndroidManifest.xml40
-rw-r--r--tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/Android.bp30
-rw-r--r--tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/AndroidManifest.xml38
-rw-r--r--tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/AndroidManifest.xml26
-rw-r--r--tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/AndroidManifest.xml26
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/Android.bp24
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/Android.bp24
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/AndroidManifest.xml32
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/Android.bp24
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/Android.bp24
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/Android.bp26
-rw-r--r--tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionpolicy/OWNERS7
-rw-r--r--tests/cts/permissionpolicy/res/raw/OWNERS8
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml8082
-rw-r--r--tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml573
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/CommandBroadcastReceiver.java49
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java94
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/IntelligenceRolesPolicyTest.java99
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java69
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoProcessOutgoingCallPermissionTest.java142
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java277
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoWriteSecureSettingsPermissionTest.java47
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java58
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionPolicyTest.java533
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PrivappPermissionsTest.java251
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ProtectedBroadcastsTest.java121
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedPermissionsTest.java745
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionSharedUidTest.java269
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionTest.java755
-rw-r--r--tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RuntimePermissionProperties.kt172
-rw-r--r--tests/cts/permissionui/Android.bp84
-rw-r--r--tests/cts/permissionui/AndroidManifest.xml89
-rw-r--r--tests/cts/permissionui/AndroidTest.xml102
-rw-r--r--tests/cts/permissionui/AppThatAccessesCameraAndMic/Android.bp35
-rw-r--r--tests/cts/permissionui/AppThatAccessesCameraAndMic/AndroidManifest.xml35
-rw-r--r--tests/cts/permissionui/AppThatAccessesCameraAndMic/src/android/permissionui/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt241
-rw-r--r--tests/cts/permissionui/CreateNotificationChannelsApp31/Android.bp33
-rw-r--r--tests/cts/permissionui/CreateNotificationChannelsApp31/AndroidManifest.xml44
-rw-r--r--tests/cts/permissionui/CreateNotificationChannelsApp31/src/android/permissionui/cts/usepermission/CreateNotificationChannelsActivity.kt172
-rw-r--r--tests/cts/permissionui/DifferentPkgNameApp/Android.bp33
-rw-r--r--tests/cts/permissionui/DifferentPkgNameApp/AndroidManifest.xml33
-rw-r--r--tests/cts/permissionui/DifferentPkgNameApp/src/android/permissionui/cts/usepermissionother/EmptyActivity.kt21
-rw-r--r--tests/cts/permissionui/HelperAppOverlay/Android.bp32
-rw-r--r--tests/cts/permissionui/HelperAppOverlay/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionui/HelperAppOverlay/src/android/permissionui/cts/helper/overlay/OverlayActivity.kt26
-rw-r--r--tests/cts/permissionui/ImplicitUserSelectStorageApp/Android.bp33
-rw-r--r--tests/cts/permissionui/ImplicitUserSelectStorageApp/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionui/MediaPermissionApp33WithStorage/Android.bp32
-rw-r--r--tests/cts/permissionui/MediaPermissionApp33WithStorage/AndroidManifest.xml29
-rw-r--r--tests/cts/permissionui/OWNERS4
-rw-r--r--tests/cts/permissionui/PermissionPolicyApp25/Android.bp31
-rw-r--r--tests/cts/permissionui/PermissionPolicyApp25/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionui/PermissionPolicyApp25/src/android/permissionui/cts/permissionpolicy/TestProtectionFlagsActivity.kt108
-rw-r--r--tests/cts/permissionui/StorageApp33/Android.bp33
-rw-r--r--tests/cts/permissionui/StorageApp33/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionui/TEST_MAPPING32
-rw-r--r--tests/cts/permissionui/UsePermissionApp22/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp22/AndroidManifest.xml79
-rw-r--r--tests/cts/permissionui/UsePermissionApp22CalendarOnly/Android.bp33
-rw-r--r--tests/cts/permissionui/UsePermissionApp22CalendarOnly/AndroidManifest.xml36
-rw-r--r--tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/CheckPermissionService.kt42
-rw-r--r--tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/StartCheckPermissionServiceActivity.kt31
-rw-r--r--tests/cts/permissionui/UsePermissionApp22None/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp22None/AndroidManifest.xml30
-rw-r--r--tests/cts/permissionui/UsePermissionApp23/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp23/AndroidManifest.xml76
-rw-r--r--tests/cts/permissionui/UsePermissionApp25/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp25/AndroidManifest.xml76
-rw-r--r--tests/cts/permissionui/UsePermissionApp26/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp26/AndroidManifest.xml34
-rw-r--r--tests/cts/permissionui/UsePermissionApp28/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp28/AndroidManifest.xml32
-rw-r--r--tests/cts/permissionui/UsePermissionApp29/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp29/AndroidManifest.xml33
-rw-r--r--tests/cts/permissionui/UsePermissionApp30/Android.bp33
-rw-r--r--tests/cts/permissionui/UsePermissionApp30/AndroidManifest.xml43
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBackground/Android.bp32
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBackground/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBackground/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt54
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBluetooth/Android.bp34
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBluetooth/AndroidManifest.xml38
-rw-r--r--tests/cts/permissionui/UsePermissionApp30WithBluetooth/src/android/permissionui/cts/usepermission/AccessBluetoothOnCommand.kt145
-rw-r--r--tests/cts/permissionui/UsePermissionApp31/Android.bp33
-rw-r--r--tests/cts/permissionui/UsePermissionApp31/AndroidManifest.xml31
-rw-r--r--tests/cts/permissionui/UsePermissionApp32/Android.bp34
-rw-r--r--tests/cts/permissionui/UsePermissionApp32/AndroidManifest.xml26
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/Android.bp40
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml53
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/CheckCalendarAccessActivity.kt69
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/FinishOnCreateActivity.kt29
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt93
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatestNone/Android.bp33
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatestNone/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionui/UsePermissionAppLocationProvider/Android.bp31
-rw-r--r--tests/cts/permissionui/UsePermissionAppLocationProvider/AndroidManifest.xml37
-rw-r--r--tests/cts/permissionui/UsePermissionAppLocationProvider/res/values/strings.xml (renamed from PermissionController/res/values-w764dp-v33/dimens.xml)6
-rw-r--r--tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/AddLocationProviderActivity.kt40
-rw-r--r--tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/UseMicrophoneActivity.kt67
-rw-r--r--tests/cts/permissionui/UsePermissionAppStreaming/Android.bp34
-rw-r--r--tests/cts/permissionui/UsePermissionAppStreaming/AndroidManifest.xml28
-rw-r--r--tests/cts/permissionui/UsePermissionAppStreaming/src/android/permissionui/cts/usepermission/RequestPermissionActivity.kt30
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/Android.bp35
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/AndroidManifest.xml29
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/res/drawable/border.xml25
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/res/layout/overlay_activity.xml34
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/strings.xml19
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/styles.xml22
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/OverlayActivity.kt55
-rw-r--r--tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt97
-rw-r--r--tests/cts/permissionui/res/raw/lg_g4_iso_800_jpg.jpgbin0 -> 107684 bytes
-rw-r--r--tests/cts/permissionui/res/raw/test_video.mp4bin0 -> 135632 bytes
-rwxr-xr-x[-rw-r--r--]tests/cts/permissionui/res/values-en-rGB/strings.xml (renamed from PermissionController/res/values-w764dp-v34/dimens.xml)6
-rwxr-xr-xtests/cts/permissionui/res/values/strings.xml28
-rw-r--r--tests/cts/permissionui/res/xml/test_accessibilityservice.xml21
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt542
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppMetadata.kt210
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt210
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/AppStreamingPermissionTest.kt194
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt467
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt1263
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt643
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/LocationAccuracyTest.kt168
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/LocationProviderInterceptDialogTest.kt148
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt182
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionUpgradeTest.kt62
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/MultiDevicePermissionTest.kt54
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/NoPermissionTest.kt46
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/NotificationPermissionTest.kt409
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt131
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionGroupTest.kt90
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionNoOpGtsTest.kt30
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionPolicyTest25.kt63
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt285
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionRationaleTest.kt398
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTapjackingTest.kt95
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTest.kt171
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt120
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTapjackingTest.kt132
-rwxr-xr-xtests/cts/permissionui/src/android/permissionui/cts/PermissionTest22.kt67
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt387
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTest29.kt211
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30.kt88
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30WithBluetooth.kt200
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionUpgradeTest.kt158
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionUsageInfoTest.kt58
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerPermissionTest.kt485
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerUtils.kt117
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt212
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt459
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/SafetyProtectionTest.kt123
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/SensorBlockedBannerTest.kt172
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/StartForFutureActivity.kt59
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/TestInstallerActivity.kt21
-rw-r--r--tests/cts/role/Android.bp49
-rw-r--r--tests/cts/role/AndroidManifest.xml40
-rw-r--r--tests/cts/role/AndroidTest.xml51
-rw-r--r--tests/cts/role/CtsRoleTestApp/Android.bp26
-rw-r--r--tests/cts/role/CtsRoleTestApp/AndroidManifest.xml131
-rw-r--r--tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultDialerActivity.java52
-rw-r--r--tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultSmsActivity.java52
-rw-r--r--tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/IsRoleHeldActivity.java46
-rw-r--r--tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/RequestRoleActivity.java53
-rw-r--r--tests/cts/role/CtsRoleTestApp28/Android.bp27
-rw-r--r--tests/cts/role/CtsRoleTestApp28/AndroidManifest.xml79
-rw-r--r--tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultDialerActivity.java40
-rw-r--r--tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultSmsActivity.java41
-rw-r--r--tests/cts/role/CtsRoleTestApp33WithoutInCallService/Android.bp23
-rw-r--r--tests/cts/role/CtsRoleTestApp33WithoutInCallService/AndroidManifest.xml37
-rw-r--r--tests/cts/role/OWNERS3
-rw-r--r--tests/cts/role/TEST_MAPPING48
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleControllerManagerTest.kt157
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleManagerTest.java1227
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt202
-rw-r--r--tests/cts/role/src/android/app/role/cts/WaitForResultActivity.java75
-rw-r--r--tests/cts/safetycenter/AndroidTest.xml3
-rw-r--r--tests/cts/safetycenter/TEST_MAPPING2
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt62
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt80
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt228
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt39
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt4
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt16
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt204
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt4
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt4
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt10
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt8
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt44
-rw-r--r--tests/cts/safetycenter/src/android/safetycenter/cts/ui/SafetyCenterActivityTest.kt33
-rw-r--r--tests/functional/safetycenter/multiusers/AndroidTest.xml3
-rw-r--r--tests/functional/safetycenter/multiusers/TEST_MAPPING27
-rw-r--r--tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt428
-rw-r--r--tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml3
-rw-r--r--tests/functional/safetycenter/safetycenteractivity/TEST_MAPPING2
-rw-r--r--tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt150
-rw-r--r--tests/functional/safetycenter/singleuser/AndroidManifest.xml9
-rw-r--r--tests/functional/safetycenter/singleuser/AndroidTest.xml3
-rw-r--r--tests/functional/safetycenter/singleuser/TEST_MAPPING2
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt1234
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt286
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterShellCommandsTest.kt (renamed from tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterShellCommandsTest.kt)46
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterQsActivityTest.kt92
-rw-r--r--tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt83
-rw-r--r--tests/functional/safetycenter/subpages/Android.bp43
-rw-r--r--tests/functional/safetycenter/subpages/AndroidManifest.xml30
-rw-r--r--tests/functional/safetycenter/subpages/AndroidTest.xml64
-rw-r--r--tests/functional/safetycenter/subpages/TEST_MAPPING17
-rw-r--r--tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt (renamed from tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt)85
-rw-r--r--tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt (renamed from tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt)86
-rw-r--r--tests/hostside/safetycenter/Android.bp1
-rw-r--r--tests/hostside/safetycenter/AndroidTest.xml3
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt11
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt11
-rw-r--r--tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt66
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt36
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterSystemEventReportedLoggingHostTest.kt57
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetySourceStateCollectedLoggingHostTest.kt14
-rw-r--r--tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt19
-rw-r--r--tests/utils/safetycenter/AndroidManifest.xml27
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt14
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/EnableSensorRule.kt72
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/NotificationCharacteristics.kt (renamed from tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/NotificationCharacteristics.kt)4
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterActivityLauncher.kt18
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterEnabledChangedReceiver.kt16
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt59
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt42
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestHelper.kt25
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt84
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestRule.kt57
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceIntentHandler.kt14
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceReceiver.kt38
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt38
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/StatusBarNotificationWithChannel.kt (renamed from tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/StatusBarNotificationWithChannel.kt)2
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenter.kt29
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenterRule.kt50
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/TestActivity.kt34
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt (renamed from tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/TestNotificationListener.kt)116
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/UiTestHelper.kt85
-rw-r--r--tests/utils/safetycenter/java/com/android/safetycenter/testing/WaitForBroadcasts.kt74
1260 files changed, 72915 insertions, 7830 deletions
diff --git a/Android.bp b/Android.bp
index 4a436da6c..bf7437814 100644
--- a/Android.bp
+++ b/Android.bp
@@ -30,7 +30,6 @@ apex_defaults {
systemserverclasspath_fragments: ["com.android.permission-systemserverclasspath-fragment"],
prebuilts: [
"current_sdkinfo",
- "privapp_allowlist_com.android.permissioncontroller.xml",
],
key: "com.android.permission.key",
certificate: ":com.android.permission.certificate",
diff --git a/OWNERS b/OWNERS
index 8f1443bc6..cd03f0db3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,5 @@
+#Bug component: 137825
+
include platform/frameworks/base:/core/java/android/permission/OWNERS
include platform/packages/modules/common:/MODULES_OWNERS # see go/mainline-owners-policy
diff --git a/PermissionController/Android.bp b/PermissionController/Android.bp
index cd0ceab01..d0713a729 100644
--- a/PermissionController/Android.bp
+++ b/PermissionController/Android.bp
@@ -82,7 +82,7 @@ android_app {
privileged: true,
certificate: "platform",
rename_resources_package: false,
- required: ["privapp_allowlist_com.android.permissioncontroller.xml"],
+ privapp_allowlist: ":privapp_allowlist_com.android.permissioncontroller.xml",
srcs: [":permissioncontroller-sources"],
@@ -152,6 +152,12 @@ android_app {
"lottie",
"safety-label",
"role-controller",
+ "permissions-flags-lib",
+ "androidx.compose.foundation_foundation",
+ "androidx.compose.runtime_runtime",
+ "androidx.compose.runtime_runtime-livedata",
+ "androidx.compose.ui_ui",
+ "androidx.wear.compose_compose-material",
],
proto: {
@@ -165,6 +171,7 @@ android_app {
},
optimize: {
+ proguard_compatibility: false, // TODO(b/215530220): remove when this is default behavior
proguard_flags_files: ["proguard.flags"],
},
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 874ba35d6..288dc6c84 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -270,8 +270,7 @@
android:windowSoftInputMode="stateAlwaysHidden|adjustNothing"
android:visibleToInstantApps="true"
android:inheritShowWhenLocked="true"
- android:hardwareAccelerated="false"
- android:canDisplayOnRemoteDevices="false">
+ android:canDisplayOnRemoteDevices="@bool/is_at_least_v">
<intent-filter android:priority="1">
<action android:name="android.content.pm.action.REQUEST_PERMISSIONS" />
<category android:name="android.intent.category.DEFAULT" />
@@ -291,7 +290,7 @@
android:visibleToInstantApps="true"
android:inheritShowWhenLocked="true"
android:hardwareAccelerated="false"
- android:canDisplayOnRemoteDevices="false">
+ android:canDisplayOnRemoteDevices="@bool/is_at_least_v">
</activity>
<activity android:name="com.android.permissioncontroller.permission.ui.ManagePermissionsActivity"
@@ -399,6 +398,7 @@
<activity android:name="com.android.permissioncontroller.role.ui.RequestRoleActivity"
android:excludeFromRecents="true"
android:exported="true"
+ android:launchMode="singleTop"
android:theme="@style/RequestRole.FilterTouches">
<intent-filter android:priority="1">
<action android:name="android.app.role.action.REQUEST_ROLE" />
@@ -577,7 +577,7 @@
</receiver>
<activity android:name="com.android.permissioncontroller.incident.ConfirmationActivity"
- android:theme="@style/Theme.DeviceDefault.Dialog.NoActionBar.DayNight"
+ android:theme="@style/Theme.PermissionController.IncidentReportDialog"
android:exported="false"
android:excludeFromRecents="true"
android:finishOnCloseSystemDialogs="true"
@@ -606,8 +606,6 @@
</intent-filter>
</activity>
- <!-- Unexported empty activity for in-process tests -->
- <activity android:name="android.app.Activity" />
</application>
</manifest>
diff --git a/PermissionController/TEST_MAPPING b/PermissionController/TEST_MAPPING
index 0ae3818fd..a7f2aec54 100644
--- a/PermissionController/TEST_MAPPING
+++ b/PermissionController/TEST_MAPPING
@@ -16,17 +16,17 @@
"name": "PermissionUiTestCases",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
],
"presubmit-large": [
{
- "name": "CtsPermission3TestCases",
+ "name": "CtsPermissionUiTestCases",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
@@ -43,7 +43,7 @@
"exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
},
{
- "exclude-annotation": "androidx.test.filters.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
],
"file_patterns": ["res/xml/roles\\.xml"]
@@ -52,7 +52,7 @@
"name": "PermissionUiTestCases[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
},
// TODO(b/238773220): These tests currently fails on R base image
{
@@ -73,14 +73,65 @@
]
},
{
- "name": "CtsPermission3TestCases[com.google.android.permission.apex]",
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
],
+ "postsubmit": [
+ {
+ "name": "CtsRoleTestCases",
+ "file_patterns": ["res/xml/roles\\.xml"]
+ },
+ {
+ "name": "PermissionUiTestCases"
+ },
+ {
+ "name": "CtsPermissionUiTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
+ }
+ ],
+ "file_patterns": ["res/xml/roles\\.xml"]
+ },
+ {
+ "name": "PermissionUiTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238773220): These tests currently fails on R base image
+ {
+ "exclude-filter": "com.android.permissioncontroller.permissionui.ui.handheld.ManageCustomPermissionsFragmentTest#groupSummaryGetsUpdatedWhenPermissionGetsGranted"
+ },
+ {
+ "exclude-filter": "com.android.permissioncontroller.permissionui.ui.handheld.ManageCustomPermissionsFragmentTest#groupSummaryGetsUpdatedWhenPermissionGetsRevoked"
+ },
+ {
+ "exclude-filter": "com.android.permissioncontroller.permissionui.ui.handheld.ManageStandardPermissionsFragmentTest#additionalPermissionSummaryGetUpdateWhenAppGetsInstalled"
+ },
+ {
+ "exclude-filter": "com.android.permissioncontroller.permissionui.ui.handheld.ManageStandardPermissionsFragmentTest#additionalPermissionSummaryGetUpdateWhenDefinerGetsUninstalled"
+ },
+ {
+ "exclude-filter": "com.android.permissioncontroller.permissionui.ui.handheld.ManageStandardPermissionsFragmentTest#additionalPermissionSummaryGetUpdateWhenUserGetsUninstalled"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]"
+ }
+ ],
"imports": [
{
"path": "vendor/xts/gts-tests/hostsidetests/permissioncontroller"
diff --git a/PermissionController/lint-baseline.xml b/PermissionController/lint-baseline.xml
index 05a307234..546ed596d 100644
--- a/PermissionController/lint-baseline.xml
+++ b/PermissionController/lint-baseline.xml
@@ -3,61 +3,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessAt`"
- errorLine1=" val attributedOpEntry: AttributedOpEntry = it.getDiscreteAccessAt(i)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
- line="191"
- column="67"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessAt`"
- errorLine1=" val opEntry: AttributedOpEntry = it.getDiscreteAccessAt(i)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
- line="156"
- column="57"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessCount`"
- errorLine1=" for (i in 0 until it.discreteAccessCount) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
- line="155"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessCount`"
- errorLine1=" for (i in 0 until it.discreteAccessCount) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
- line="190"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOpsRequest.Builder#setHistoryFlags`"
- errorLine1=" .setHistoryFlags(HISTORY_FLAG_DISCRETE or HISTORY_FLAG_GET_ATTRIBUTION_CHAINS)"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt"
- line="101"
- column="18"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level 31 (current min is 30): `android.apphibernation.AppHibernationManager#isHibernatingForUser`"
errorLine1=" if (hibernationManager.isHibernatingForUser(pkg.packageName)) {"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
@@ -180,17 +125,6 @@
<issue
id="NewApi"
message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterData#getIssues`"
- errorLine1=" ) : this(safetyCenterData.status, hasIssues = safetyCenterData.issues.size &gt; 0)"
- errorLine2=" ~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="18"
- column="68"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterData#getIssues`"
errorLine1=" issues"
errorLine2=" ~~~~~~">
<location
@@ -213,17 +147,6 @@
<issue
id="NewApi"
message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterData#getStatus`"
- errorLine1=" ) : this(safetyCenterData.status, hasIssues = safetyCenterData.issues.size &gt; 0)"
- errorLine2=" ~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="18"
- column="31"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterData#getStatus`"
errorLine1=" status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS"
errorLine2=" ~~~~~~">
<location
@@ -356,17 +279,6 @@
<issue
id="NewApi"
message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterStatus#getRefreshStatus`"
- errorLine1=" when (status.refreshStatus) {"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="65"
- column="26"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterStatus#getRefreshStatus`"
errorLine1=" status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS"
errorLine2=" ~~~~~~~~~~~~~">
<location
@@ -421,39 +333,6 @@
<issue
id="NewApi"
- message="Call requires API level 34 (current min is 33): `getParentGroupId`"
- errorLine1=" String groupId = getParentGroupId(preferenceKey);"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
- line="89"
- column="30"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 34 (current min is 33): `openRelevantSubpage`"
- errorLine1=" frag = openRelevantSubpage(groupId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
- line="86"
- column="20"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 34 (current min is 33): `openRelevantSubpage`"
- errorLine1=" frag = openRelevantSubpage(groupId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
- line="90"
- column="20"/>
- </issue>
-
- <issue
- id="NewApi"
message="Class requires API level 31 (current min is 30): `android.apphibernation.AppHibernationManager`"
errorLine1=" userContext.getSystemService(APP_HIBERNATION_SERVICE) as AppHibernationManager"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
@@ -498,68 +377,93 @@
<issue
id="NewApi"
- message="Class requires API level 34 (current min is 30): `android.app.AppOpsManager.OnOpNotedListener`"
- errorLine1=" AppOpsManager.OnOpNotedListener,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Field requires API level 33 (current min is 30): `getTAG`"
+ errorLine1=" MoreIssuesCardPreference.TAG,"
+ errorLine2=" ~~~">
+ <location
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt"
+ line="107"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessAt`">
+ <location
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
+ line="153"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessAt`">
+ <location
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
+ line="188"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessCount`">
+ <location
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
+ line="152"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOp#getDiscreteAccessCount`">
+ <location
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/v31/LightHistoricalPackageOps.kt"
+ line="187"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.app.AppOpsManager.HistoricalOpsRequest.Builder#setHistoryFlags`">
<location
file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt"
- line="45"
- column="5"/>
+ line="104"/>
</issue>
<issue
id="NewApi"
- message="Class requires API level 34 (current min is 30): `android.app.AppOpsManager.OnOpNotedListener`"
- errorLine1=" AppOpsManager.OnOpNotedListener,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 34 (current min is 33): `getParentGroupId`">
<location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt"
- line="38"
- column="5"/>
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
+ line="91"/>
</issue>
<issue
id="NewApi"
- message="Field requires API level 33 (current min is 30): `getTAG`"
- errorLine1=" MoreIssuesCardPreference.TAG,"
- errorLine2=" ~~~">
+ message="Call requires API level 34 (current min is 33): `openRelevantSubpage`">
<location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt"
- line="107"
- column="46"/>
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
+ line="88"/>
</issue>
<issue
id="NewApi"
- message="Method reference requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterStatus::severityLevel`"
- errorLine1=" val severityLevel: Int by status::severityLevel"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 34 (current min is 33): `openRelevantSubpage`">
<location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="30"
- column="31"/>
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java"
+ line="92"/>
</issue>
<issue
id="NewApi"
- message="Method reference requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterStatus::summary`"
- errorLine1=" val originalSummary: CharSequence by status::summary"
- errorLine2=" ~~~~~~~~~~~~~~~">
+ message="Class requires API level 34 (current min is 30): `android.app.AppOpsManager.OnOpNotedListener`">
<location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="29"
- column="42"/>
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt"
+ line="46"/>
</issue>
<issue
id="NewApi"
- message="Method reference requires API level 33 (current min is 30): `android.safetycenter.SafetyCenterStatus::title`"
- errorLine1=" val title: CharSequence by status::title"
- errorLine2=" ~~~~~~~~~~~~~">
+ message="Class requires API level 34 (current min is 30): `android.app.AppOpsManager.OnOpNotedListener`">
<location
- file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/StatusUiData.kt"
- line="28"
- column="32"/>
+ file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightPackageOpsLiveData.kt"
+ line="43"/>
</issue>
</issues> \ No newline at end of file
diff --git a/PermissionController/proguard.flags b/PermissionController/proguard.flags
index 13590aa39..292e3e4f4 100644
--- a/PermissionController/proguard.flags
+++ b/PermissionController/proguard.flags
@@ -31,3 +31,13 @@
*** set*(***);
*** has*();
}
+
+# Strip verbose logs.
+-assumenosideeffects class android.util.Log {
+ static *** v(...);
+ static *** isLoggable(...);
+}
+-assumenosideeffects class android.util.Slog {
+ static *** v(...);
+}
+-maximumremovedandroidloglevel 2
diff --git a/PermissionController/res/drawable/ic_more_horizontal.xml b/PermissionController/res/drawable/ic_more_horizontal.xml
new file mode 100644
index 000000000..c770e08ef
--- /dev/null
+++ b/PermissionController/res/drawable/ic_more_horizontal.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
+</vector>
diff --git a/PermissionController/res/layout-w764dp-v33/action_button_list.xml b/PermissionController/res/layout-v33/action_button_list_large_screen.xml
index 4db6df47c..141290fa2 100644
--- a/PermissionController/res/layout-w764dp-v33/action_button_list.xml
+++ b/PermissionController/res/layout-v33/action_button_list_large_screen.xml
@@ -16,6 +16,4 @@
<com.android.permissioncontroller.safetycenter.ui.EqualWidthContainer
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/action_button_list"
style="@style/SafetyCenterIssueActionButtonList" />
diff --git a/PermissionController/res/layout-v33/spaced_preference_category_no_label.xml b/PermissionController/res/layout-v33/action_button_list_small_screen.xml
index cecdc8bcd..048ac4595 100644
--- a/PermissionController/res/layout-v33/spaced_preference_category_no_label.xml
+++ b/PermissionController/res/layout-v33/action_button_list_small_screen.xml
@@ -14,5 +14,5 @@
~ limitations under the License.
-->
-<Space
- style="@style/SafetyCenterNoLabelPreferenceCategory"/> \ No newline at end of file
+<LinearLayout
+ style="@style/SafetyCenterIssueActionButtonList" />
diff --git a/PermissionController/res/layout-v33/action_button_list.xml b/PermissionController/res/layout-v33/preference_entries_top_padding.xml
index 3217f4c78..0e6e27148 100644
--- a/PermissionController/res/layout-v33/action_button_list.xml
+++ b/PermissionController/res/layout-v33/preference_entries_top_padding.xml
@@ -14,7 +14,7 @@
~ limitations under the License.
-->
-<LinearLayout
+<Space
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/action_button_list"
- style="@style/SafetyCenterIssueActionButtonList" />
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/sc_spacing_xsmall" /> \ No newline at end of file
diff --git a/PermissionController/res/layout-v33/preference_issue_card.xml b/PermissionController/res/layout-v33/preference_issue_card.xml
index 571efae3b..e6d749142 100644
--- a/PermissionController/res/layout-v33/preference_issue_card.xml
+++ b/PermissionController/res/layout-v33/preference_issue_card.xml
@@ -54,7 +54,7 @@
<include
android:id="@+id/issue_card_action_button_list"
- layout="@layout/action_button_list"/>
+ layout="?attr/scActionButtonListLayout"/>
<com.android.permissioncontroller.permission.ui.v33.widget.SafetyProtectionSectionView
android:id="@+id/issue_card_protected_by_android"
@@ -72,10 +72,10 @@
android:text="@string/safety_center_resolved_issue_fallback"
style="@style/SafetyCenterIssueCardResolvedTitle" />
- <!-- This group doesn't contain issue_card_dismiss_btn, issue_card_subtitle or
- issue_card_protected_by_android since the version of ConstraintLayout we're
- using doesn't allow us to override the group's visibility on individual group
- members. See b/242705351 for context. -->
+ <!-- This group doesn't contain issue_card_attribution_title, issue_card_dismiss_btn,
+ issue_card_subtitle or issue_card_protected_by_android since the version of
+ ConstraintLayout we're using doesn't allow us to override the group's visibility on
+ individual group members. See b/242705351 for context. -->
<androidx.constraintlayout.widget.Group
android:id="@+id/default_issue_content"
android:layout_width="wrap_content"
diff --git a/PermissionController/res/layout/grant_permissions.xml b/PermissionController/res/layout/grant_permissions.xml
index 9becddb7f..4b23dd959 100644
--- a/PermissionController/res/layout/grant_permissions.xml
+++ b/PermissionController/res/layout/grant_permissions.xml
@@ -184,7 +184,7 @@
<com.android.permissioncontroller.permission.ui.widget.SecureButton
android:id="@+id/permission_dont_allow_more_selected_button"
android:text="@string/grant_dialog_button_dont_select_more"
- style="@style/PermissionGrantButtonDeny" />
+ style="@style/PermissionGrantButtonDontAllowMore" />
</LinearLayout>
</LinearLayout>
diff --git a/PermissionController/res/navigation-watch/nav_graph.xml b/PermissionController/res/navigation-watch/nav_graph.xml
new file mode 100644
index 000000000..7af2c3e39
--- /dev/null
+++ b/PermissionController/res/navigation-watch/nav_graph.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/nav_graph"
+ app:startDestination="@id/manage_standard">
+
+ <!-- For explanation of the navigation component, and this graph, see
+ https://developer.android.com/guide/navigation -->
+
+ <fragment
+ android:id="@+id/manage_standard"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearManageStandardPermissionsFragment"
+ android:label="ManageStandard">
+
+ <action
+ android:id="@+id/standard_to_custom"
+ app:destination="@id/manage_custom"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popEnterAnim="@anim/activity_close_enter"
+ app:popExitAnim="@anim/activity_close_exit"/>
+
+ <action
+ android:id="@+id/manage_to_perm_apps"
+ app:destination="@id/permission_apps"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popEnterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"/>
+
+ <action
+ android:id="@+id/manage_to_auto_revoke"
+ app:destination="@id/auto_revoke"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popEnterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"/>
+
+ </fragment>
+
+ <fragment
+ android:id="@+id/manage_custom"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearManageCustomPermissionsFragment"
+ android:label="ManageCustom">
+
+ <action
+ android:id="@+id/manage_to_perm_apps"
+ app:destination="@id/permission_apps"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+
+ </fragment>
+
+ <fragment
+ android:id="@+id/auto_revoke"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearUnusedAppsFragment"
+ android:label="AutoRevoke">
+
+ <action
+ android:id="@+id/auto_revoke_to_app_perms"
+ app:destination="@id/app_permission_groups"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+
+ </fragment>
+
+ <fragment
+ android:id="@+id/app_permission_groups"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearAppPermissionGroupsFragment"
+ android:label="AppPermissionGroups">
+
+ <action
+ android:id="@+id/perm_groups_to_app"
+ app:destination="@id/app_permission"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+
+ <action
+ android:id="@+id/perm_groups_to_all_perms"
+ app:destination="@id/all_app_permissions"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+
+ <action
+ android:id="@+id/perm_groups_to_custom"
+ app:destination="@id/custom_app_permission_groups"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+ </fragment>
+
+ <fragment
+ android:id="@+id/app_permission"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearAppPermissionFragment"
+ android:label="AppPermission" />
+
+ <fragment
+ android:id="@+id/permission_apps"
+ android:name="com.android.permissioncontroller.permission.ui.wear.WearPermissionAppsFragment"
+ android:label="PermissionApps">
+
+ <action
+ android:id="@+id/perm_apps_to_app"
+ app:destination="@id/app_permission"
+ app:enterAnim="@anim/activity_open_enter"
+ app:popExitAnim="@anim/activity_close_exit"
+ app:popEnterAnim="@anim/activity_open_enter"/>
+ </fragment>
+</navigation>
diff --git a/PermissionController/res/values-af-v33/strings.xml b/PermissionController/res/values-af-v33/strings.xml
index 2d81b6946..6d6a118cd 100644
--- a/PermissionController/res/values-af-v33/strings.xml
+++ b/PermissionController/res/values-af-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Meer waarskuwings"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Waarskuwings wat toegemaak is"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Vou uit om nog een waarskuwing te sien}other{Vou uit om nog # waarskuwings te sien}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Waarskuwing. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Handeling is voltooi"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Gaan instellings na wat jou toestel kan beskerm"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Kitsinstellings vir sekuriteit en privaatheid"</string>
diff --git a/PermissionController/res/values-af/strings.xml b/PermissionController/res/values-af/strings.xml
index ebd2dff4f..db581567b 100644
--- a/PermissionController/res/values-af/strings.xml
+++ b/PermissionController/res/values-af/strings.xml
@@ -57,7 +57,7 @@
<string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Laat altyd toe"</string>
<string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"Laat toe dat alle lêers bestuur word"</string>
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"Laat toegang tot medialêers toe"</string>
- <string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Programme"</string>
+ <string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
<string name="app_permissions" msgid="3369917736607944781">"Programtoestemmings"</string>
<string name="unused_apps" msgid="2058057455175955094">"Ongebruikte programme"</string>
<string name="no_unused_apps" msgid="12809387670415295">"Geen ongebruikte programme nie"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Laat altyd toe"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Laat net toe terwyl jy program gebruik"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Laat net toe terwyl jy app gebruik"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Moenie toelaat nie"</string>
<string name="loading" msgid="4789365003890741082">"Laai tans …"</string>
<string name="all_permissions" msgid="6911125611996872522">"Alle toestemmings"</string>
@@ -187,7 +187,7 @@
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Laat toe dat alle lêers bestuur word"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Laat net toegang tot media toe"</string>
<string name="app_permission_button_allow_always" msgid="4573292371734011171">"Laat altyd toe"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Laat net toe terwyl jy program gebruik"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Laat net toe terwyl jy app gebruik"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Laat altyd alles toe"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Vra elke keer"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Moenie toelaat nie"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"<xliff:g id="DATE">%s</xliff:g> laas oopgemaak"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"As jy toelaat dat alle lêers bestuur word, kan hierdie program enige lêers in gedeelde bergingspasie op hierdie toestel en gekoppelde bergingtoestelle kry, wysig en uitvee. Die program kan toegang tot lêers kry sonder om jou te vra."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Laat hierdie program toe om lêers op die toestel en enige gekoppelde bergingtoestelle te kry, te wysig en uit te vee? Hierdie program kan toegang tot lêers kry sonder om jou te vra."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Programme met hierdie toestemming <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Apps met hierdie toestemming <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Programme met hierdie toestemming kan ingaan by fisieke aktiwiteit, soos stap, fietsry, ry, treëtelling, en meer"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Programme met hierdie toestemming kan toegang tot jou kalender kry"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Programme met hierdie toestemming kan foonoproeprekord lees en skryf"</string>
@@ -337,7 +337,7 @@
<string name="app_perms_content_provider_7d_all_files" msgid="7962416229708835558">"In afgelope 7 dae gebruik • Alle lêers"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"Geen toestemmings toegelaat nie"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"Geen toestemmings geweier nie"</string>
- <string name="no_apps_allowed" msgid="7718822655254468631">"Geen programme toegelaat nie"</string>
+ <string name="no_apps_allowed" msgid="7718822655254468631">"Geen apps toegelaat nie"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"Geen programme het toestemming vir alle lêers nie"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Geen programme het toestemming net vir media nie"</string>
<string name="no_apps_denied" msgid="7663435886986784743">"Geen programme geweier nie"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Wys assistent-aktiveringbespeuring"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Wys ikoon in statusbalk wanneer mikrofoon gebruik word om stemassistent te aktiveer"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou foto\'s en media op jou toestel?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou kontakte?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot hierdie toestel se ligging?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Die program sal net toegang tot die ligging hê terwyl jy die program gebruik"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot hierdie toestel se ligging?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Hierdie program wil dalk die hele tyd toegang tot jou ligging hê, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Verander liggingtoegang vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Hierdie program wil die hele tyd toegang tot jou ligging hê, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om toestelle in die omtrek te soek, aan hulle te koppel en hul relatiewe posisie te bepaal?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om toestelle in die omtrek te soek, aan hulle te koppel en hul relatiewe posisie te bepaal? "<annotation id="link">"Laat toe in Instellings."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Verander <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> se liggingtoegang van benaderd na presies?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot hierdie toestel se benaderde ligging?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Presies"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Benaderd"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou kalender?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om SMS\'e te stuur en te bekyk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Gee vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot foto\'s, media en lêers op jou toestel?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot &lt;b&gt;foto\'s, video\'s, musiek en oudio&lt;/b&gt; op hierdie toestel?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot &lt;b&gt;foto\'s, video\'s, musiek, oudio en ander lêers&lt;/b&gt; op hierdie toestel?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot musiek en oudio op hierdie toestel?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot foto\'s en video\'s op hierdie toestel?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot meer foto\'s en video\'s op hierdie toestel?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om oudio op te neem?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Die program sal net kan oudio opneem terwyl jy die program gebruik"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om oudio op te neem?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Hierdie program wil dalk die hele tyd oudio opneem, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Verander mikrofoontoegang vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Hierdie program wil die hele tyd oudio opneem, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Gee &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang tot jou fisieke aktiwiteit?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om foto\'s te neem en video\'s op te neem?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Die program sal net kan foto\'s neem en video\'s opneem terwyl jy die program gebruik"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om foto\'s te neem en video\'s op te neem?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Hierdie program wil dalk die hele tyd foto\'s neem en video\'s opneem, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Verander kameratoegang vir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Hierdie program wil die hele tyd foto\'s neem en video\'s opneem, selfs wanneer jy nie die program gebruik nie. "<annotation id="link">"Laat toe in instellings."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501"><annotation id="link">"Gaan na instellings"</annotation>" om altyd 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="auto_granted_permissions" msgid="6009452264824455892">"Beheerde toestemmings"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Beheerde toestemmings"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> het liggingtoegang"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Jou organisasie gee <xliff:g id="APP_NAME">%1$s</xliff:g> toegang tot jou ligging"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Ander toestemmings"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Toestemming wat deur die stelsel gebruik word"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Toestemmings wat net deur die stelselprogramme gebruik word."</string>
@@ -574,23 +626,24 @@
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Hierdie program steun nie die jongste weergawe van Android nie. As hierdie program nie toegang tot musiek- en oudiolêers het nie, sal dit ook nie toegelaat word om toegang tot foto\'s en video\'s te kry nie."</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Gaan program met agtergrondliggingtoegang na"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> het altyd toegang tot jou ligging, selfs wanneer die program toe is"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Gaan program met agtergrondliggingtoegang na"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Gaan app met agtergrondliggingtoegang na"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Hierdie app het altyd toegang tot jou ligging, selfs wanneer dit toe is.\n\nSekere veiligheid- en noodapps moet op die agtergrond toegang tot jou ligging hê om te kan werk soos hulle moet."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Toegang is verander"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Sien onlangse ligginggebruik"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Privaatheidkontroles"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Kameratoegang"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Mikrofoontoegang"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Vir programme en dienste"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"Vir programme en dienste. As hierdie instelling af is, kan mikrofoondata steeds gedeel word wanneer jy ’n noodnommer bel."</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Vir apps en dienste"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"Vir apps en dienste. As hierdie instelling af is, kan mikrofoondata steeds gedeel word wanneer jy ’n noodnommer bel."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Sien programme en dienste met toegang tot ligging"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Wys knipbordtoegang"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Wys ’n boodskap wanneer programme toegang het tot teks, prente of ander inhoud wat jy gekopieer het"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Wys ’n boodskap wanneer apps toegang het tot teks, prente of ander inhoud wat jy gekopieer het"</string>
<string name="show_password_title" msgid="2877269286984684659">"Wys wagwoorde"</string>
<string name="show_password_summary" msgid="1110166488865981610">"Wys karakters kortliks terwyl jy tik"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Hierdie app het verklaar dat dit dalk liggingdata met derde party sal deel"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datadeling en -ligging"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Waar datadelinginligting vandaan kom"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Die ontwikkelaar het inligting aan hierdie toestel se vervaardiger verskaf oor hoe hierdie app data deel. Die ontwikkelaar kan hierdie inligting mettertyd opdateer."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Die ontwikkelaar het inligting aan "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" verskaf oor hoe hierdie app data deel. Die ontwikkelaar kan hierdie inligting mettertyd opdateer."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Hierdie app kan liggingdata deel vir:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datadeling verskil"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Dataveiligheid"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Liggingdata sal dalk gedeel word"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Hierdie app het verklaar dat dit jou liggingdata met derde partye kan deel"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Kan nie hierdie skakel oopmaak nie"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Datadelingopdaterings vir ligging"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Gaan apps na wat die manier waarop hulle jou liggingdata kan deel, verander het"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Hierdie apps het die manier waarop hulle jou liggingdata kan deel, verander. Hulle het dit dalk nie voorheen gedeel nie, of kan dit nou vir reklame- of bemarkingdoeleindes deel."</string>
diff --git a/PermissionController/res/values-am-v33/strings.xml b/PermissionController/res/values-am-v33/strings.xml
index 2967c04e8..e2a599a3c 100644
--- a/PermissionController/res/values-am-v33/strings.xml
+++ b/PermissionController/res/values-am-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ተጨማሪ ማንቂያዎች"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"የተሰናበቱ ማንቂያዎች"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ይዘርጉ እና አንድ ተጨማሪ ማንቂያ ይመልከቱ}one{ይዘርጉ እና # ተጨማሪ ማንቂያ ይመልከቱ}other{ይዘርጉ እና # ተጨማሪ ማንቂያዎችን ይመልከቱ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ማንቂያ። <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"እርምጃ ተጠናቅቋል"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"የእርስዎ መሣሪያ ላይ ጥበቃ ማከል የሚችሉ ቅንብሮችን ይፈትሹ"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"የደህንነት እና የግላዊነት ፈጣን ቅንብሮች"</string>
diff --git a/PermissionController/res/values-am/strings.xml b/PermissionController/res/values-am/strings.xml
index cd025e5f8..c3968fa48 100644
--- a/PermissionController/res/values-am/strings.xml
+++ b/PermissionController/res/values-am/strings.xml
@@ -161,9 +161,9 @@
<string name="permission_usage_bar_chart_title_last_hour" msgid="6571647509660009185">"ባለፈው 1 ሰዓት የፈቃድ አጠቃቀም"</string>
<string name="permission_usage_bar_chart_title_last_15_minutes" msgid="2743143675412824819">"ባለፉት 15 ደቂቃዎች ውስጥ የፈቃድ አጠቃቀም"</string>
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"ባለፈው 1 ደቂቃ የፈቃድ አጠቃቀም"</string>
- <string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{ባለፈው # ቀን ውስጥ ስራ ላይ አልዋለም}one{ባለፈው # ቀን ውስጥ ስራ ላይ አልዋለም}other{ባለፉት # ቀናት ውስጥ ስራ ላይ አልዋለም}}"</string>
- <string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{ባለፈው # ሰዓት ውስጥ ስራ ላይ አልዋለም}one{ባለፈው # ሰዓት ውስጥ ስራ ላይ አልዋለም}other{ባለፉት # ሰዓታት ውስጥ ስራ ላይ አልዋለም}}"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{በ1 መተግበሪያ ስራ ላይ ውሏል}one{በ# መተግበሪያዎች ስራ ላይ ውለዋል}other{በ# መተግበሪያዎች ስራ ላይ ውለዋል}}"</string>
+ <string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{ባለፈው # ቀን ውስጥ ሥራ ላይ አልዋለም}one{ባለፈው # ቀን ውስጥ ሥራ ላይ አልዋለም}other{ባለፉት # ቀናት ውስጥ ሥራ ላይ አልዋለም}}"</string>
+ <string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{ባለፈው # ሰዓት ውስጥ ሥራ ላይ አልዋለም}one{ባለፈው # ሰዓት ውስጥ ሥራ ላይ አልዋለም}other{ባለፉት # ሰዓታት ውስጥ ሥራ ላይ አልዋለም}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{በ1 መተግበሪያ ሥራ ላይ ውሏል}one{በ# መተግበሪያዎች ሥራ ላይ ውለዋል}other{በ# መተግበሪያዎች ሥራ ላይ ውለዋል}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"ሁሉንም በዳሽ ቦርድ ውስጥ ይመልከቱ"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"የተጣራው በ፦ <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"ማጣሪያን አስወግድ"</string>
@@ -200,10 +200,10 @@
<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="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_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>
@@ -218,8 +218,8 @@
<string name="auto_revoked_app_summary_one" msgid="7093213590301252970">"የ<xliff:g id="PERMISSION_NAME">%s</xliff:g> ፈቃድ ተወግዷል"</string>
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"የ<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g> እና <xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g> ፈቃዶች ተወግደዋል"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"<xliff:g id="PERMISSION_NAME">%1$s</xliff:g> እና <xliff:g id="NUMBER">%2$s</xliff:g> ሌሎች ፈቃዶች ተወግደዋል"</string>
- <string name="unused_apps_page_title" msgid="6986983535677572559">"ስራ ላይ ያልዋሉ መተግበሪያዎች"</string>
- <string name="unused_apps_page_summary" msgid="1867593913217272155">"አንድ መተግበሪያ ለጥቂት ወራት ስራ ላይ ካልዋለ፦\n\n• ውሂብዎን ለመጠበቅ ፈቃዶች ይወገዳሉ\n• ባትሪን ለመቆጠብ ማሳወቂያዎች ይቆማሉ\n• ባዶ ቦታ ለማስለቀቅ ጊዜያዊ ፋይሎች ይወገዳሉ\n\nፈቃዶችን እና ማሳወቂያዎችን እንደገና ለመፍቀድ መተግበሪያውን ይክፈቱት።"</string>
+ <string name="unused_apps_page_title" msgid="6986983535677572559">"ሥራ ላይ ያልዋሉ መተግበሪያዎች"</string>
+ <string name="unused_apps_page_summary" msgid="1867593913217272155">"አንድ መተግበሪያ ለጥቂት ወራት ሥራ ላይ ካልዋለ፦\n\n• ውሂብዎን ለመጠበቅ ፈቃዶች ይወገዳሉ\n• ባትሪን ለመቆጠብ ማሳወቂያዎች ይቆማሉ\n• ባዶ ቦታ ለማስለቀቅ ጊዜያዊ ፋይሎች ይወገዳሉ\n\nፈቃዶችን እና ማሳወቂያዎችን እንደገና ለመፍቀድ መተግበሪያውን ይክፈቱት።"</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"መተግበሪያ ለአንድ ወር ጥቅም ላይ ካልዋለ፦\n\n• ውሂብዎን ለመጠበቅ ፈቃዶች ይወገዳሉ\n• ጊዜያዊ ፋይሎች ቦታ ለማስለቀቅ ይወገዳሉ\n\nፈቃዶችን ዳግም ለመፍቀድ መተግበሪያውን ይክፈቱ።"</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{መጨረሻ የተከፈተው ከ# ወር በፊት}one{መጨረሻ የተከፈተው ከ# ወር በፊት}other{መጨረሻ የተከፈተው ከ# ወራት በፊት}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"መተግበሪያ ለመጨረሻ ጊዜ በ<xliff:g id="DATE">%s</xliff:g> ላይ ተከፍቷል"</string>
@@ -247,7 +247,7 @@
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"ተከልክሏል / በጭራሽ አልተደረሰበትም"</string>
<string name="allowed_header" msgid="7769277978004790414">"ይፈቀዳል"</string>
<string name="allowed_always_header" msgid="6455903312589013545">"ሁልጊዜ የተፈቀደ"</string>
- <string name="allowed_foreground_header" msgid="6845655788447833353">"ስራ ላይ ሲውል ብቻ የሚፈቀድ"</string>
+ <string name="allowed_foreground_header" msgid="6845655788447833353">"ሥራ ላይ ሲውል ብቻ የሚፈቀድ"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"ለሚዲያ ብቻ መዳረሻ ተፈቅዷል"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"ሁሉንም ፋይሎች ማስተዳደር ተፈቀዷል"</string>
<string name="ask_header" msgid="2633816846459944376">"ሁልጊዜ ጠይቅ"</string>
@@ -262,8 +262,8 @@
<string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> ጥቅም ላይ ያልዋሉ መተግበሪያዎች"</string>
<string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"ፈቃዶች የእርስዎን ግላዊነት ለመጠበቅ ተወግደዋል። ለመገምገም መታ ያድርጉ"</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"ጥቅም ላይ ላልዋሉ መተግበሪያዎች ፈቃዶች ተወግደዋል"</string>
- <string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"አንዳንድ መተግበሪያዎች ለጥቂት ወሮች ስራ ላይ አልዋሉም። ለመገምገም መታ ያድርጉ።"</string>
- <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# ስራ ላይ ያልዋለ መተግበሪያ}one{# ስራ ላይ ያልዋሉ መተግበሪያዎች}other{# ስራ ላይ ያልዋሉ መተግበሪያዎች}}"</string>
+ <string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"አንዳንድ መተግበሪያዎች ለጥቂት ወሮች ሥራ ላይ አልዋሉም። ለመገምገም መታ ያድርጉ።"</string>
+ <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# ሥራ ላይ ያልዋለ መተግበሪያ}one{# ሥራ ላይ ያልዋሉ መተግበሪያዎች}other{# ሥራ ላይ ያልዋሉ መተግበሪያዎች}}"</string>
<string name="unused_apps_notification_content" msgid="9195026773244581246">"ፈቃዶች እና ጊዜያዊ ፋይሎች ተወግደዋል እንዲሁም ማሳወቂያዎች ቆመዋል። ለመገምገም መታ ያድርጉ።"</string>
<string name="unused_apps_safety_center_card_title" msgid="5638409355530099149">"ፈቃዶቻቸው የተወገዱባቸው መተግበሪያዎችን ይገምግሙ"</string>
<string name="unused_apps_safety_center_card_content" msgid="1088557243627427820">"ለሆነ ያህል ጊዜ ላልተጠቀሙባቸው መተግበሪያዎች ፈቃዶች እና ጊዜያዊ ፋይሎች ተወግደዋል እና ማሳወቂያዎች ቆመዋል።"</string>
@@ -274,7 +274,7 @@
<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>
<string name="go_to_settings" msgid="1053735612211228335">"ወደ ቅንብሮች ሂድ"</string>
- <string name="auto_revoke_setting_subtitle" msgid="8631720570723050460">"አንዳንድ መተግበሪያዎች ለጥቂት ወሮች ስራ ላይ አልዋሉም።"</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>
<string name="all_unused_apps_category_title" msgid="755663524704745414">"ሁሉም ጥቅም ላይ ያልዋሉ መተግበሪያዎች"</string>
@@ -289,8 +289,8 @@
<string name="notification_listener_review_app_button_label" msgid="3433073281029143924">"ተጨማሪ አማራጮችን ይመልከቱ"</string>
<string name="notification_listener_remove_access_success_label" msgid="2477611529875633107">"መዳረሻ ተወግዷል"</string>
<string name="accessibility_access_reminder_notification_title" msgid="2971317234668807566">"ሙሉ የመሣሪያ መዳረሻ ያለውን መተግበሪያ ይገምግሙ"</string>
- <string name="accessibility_access_reminder_notification_content" msgid="7389454158175306720">"<xliff:g id="APP_NAME">%s</xliff:g> የእርስዎን ማያ ገጽ ማየት እና በመሣሪያዎ ላይ እርምጃዎችን መውሰድ ይችላል። የተደራሽነት መተግበሪያዎች እንደታሰቡት እንዲሰሩ እንደዚህ አይነት መዳረሻ ያስፈልጋቸዋል።"</string>
- <string name="accessibility_access_warning_card_content" msgid="4370327190293217358">"ይህ መተግበሪያ ማያ ገጽዎን ማየት እና በመሣሪያዎ ላይ እርምጃዎችን ማከናወን ይችላል። የተደራሽነት መተግበሪያዎች እንደታሰቡት እንዲሰሩ እንደዚህ አይነት መዳረሻ ያስፈልጋቸዋል፣ ነገር ግን መተግበሪያውን ይፈትሹት እና እንደሚያምኑት ያረጋግጡ።"</string>
+ <string name="accessibility_access_reminder_notification_content" msgid="7389454158175306720">"<xliff:g id="APP_NAME">%s</xliff:g> የእርስዎን ማያ ገፅ ማየት እና በመሣሪያዎ ላይ እርምጃዎችን መውሰድ ይችላል። የተደራሽነት መተግበሪያዎች እንደታሰቡት እንዲሰሩ እንደዚህ ዓይነት መዳረሻ ያስፈልጋቸዋል።"</string>
+ <string name="accessibility_access_warning_card_content" msgid="4370327190293217358">"ይህ መተግበሪያ ማያ ገጽዎን ማየት እና በመሣሪያዎ ላይ እርምጃዎችን ማከናወን ይችላል። የተደራሽነት መተግበሪያዎች እንደታሰቡት እንዲሰሩ እንደዚህ ዓይነት መዳረሻ ያስፈልጋቸዋል፣ ነገር ግን መተግበሪያውን ይፈትሹት እና እንደሚያምኑት ያረጋግጡ።"</string>
<string name="accessibility_remove_access_button_label" msgid="44145801526711640">"መዳረሻን አስወግድ"</string>
<string name="accessibility_show_all_apps_button_label" msgid="960067249326392280">"ሙሉ መዳረሻ ያላቸውን መተግበሪያዎች ይመልከቱ"</string>
<string name="accessibility_remove_access_success_label" msgid="4380995302917014670">"መዳረሻ ተወግዷል"</string>
@@ -345,11 +345,11 @@
<string name="settings" msgid="5409109923158713323">"ቅንብሮች"</string>
<string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"<xliff:g id="SERVICE_NAME">%s</xliff:g> ወደ የእርስዎ መሣሪያ ሙሉ መዳረሻ አለው"</string>
<string name="accessibility_service_dialog_title_multiple" msgid="5527879210683548175">"<xliff:g id="NUM_SERVICES">%s</xliff:g> ተደራሽነት መተግበሪያዎች ወደ የእርስዎ መሣሪያ ሙሉ መዳረሻ አላቸው"</string>
- <string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"<xliff:g id="SERVICE_NAME">%s</xliff:g> የእርስዎን ማያ ገጽ፣ እርምጃዎች እና ግቤቶች መመልከት፣ እርምጃዎችን መውሰድ እና ማሳያን መቆጣጠር ይችላል።"</string>
- <string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"እነዚህ መተግበሪያዎች የእርስዎን ማያ ገጽ፣ እርምጃዎች እና ግቤቶች መመልከት፣ እርምጃዎችን መውሰድ እና ማሳያን መቆጣጠር ይችላሉ።"</string>
+ <string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"<xliff:g id="SERVICE_NAME">%s</xliff:g> የእርስዎን ማያ ገፅ፣ እርምጃዎች እና ግቤቶች መመልከት፣ እርምጃዎችን መውሰድ እና ማሳያን መቆጣጠር ይችላል።"</string>
+ <string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"እነዚህ መተግበሪያዎች የእርስዎን ማያ ገፅ፣ እርምጃዎች እና ግቤቶች መመልከት፣ እርምጃዎችን መውሰድ እና ማሳያን መቆጣጠር ይችላሉ።"</string>
<string name="role_assistant_label" msgid="4727586018198208128">"ነባሪ የዲጂታል ረዳት መተግበሪያ"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"የዲጂታል ረዳት መተግበሪያ"</string>
- <string name="role_assistant_description" msgid="6622458130459922952">"ረዳት መተግበሪያዎች በሚያዩት ማያ ገጽ ላይ ባለ መረጃ ላይ ተመስርቶ ሊያግዘዎት ይችላል። አንዳንድ መተግበሪያዎች የተዋሃደ እርዳታ ለእርስዎ ለመስጠት ሁለቱንም ማስጀመሪያ እና የድምፅ ግቤት አገልግሎቶችን ይደግፋሉ።"</string>
+ <string name="role_assistant_description" msgid="6622458130459922952">"ረዳት መተግበሪያዎች በሚያዩት ማያ ገፅ ላይ ባለ መረጃ ላይ ተመስርቶ ሊያግዘዎት ይችላል። አንዳንድ መተግበሪያዎች የተዋሃደ እርዳታ ለእርስዎ ለመስጠት ሁለቱንም ማስጀመሪያ እና የድምፅ ግቤት አገልግሎቶችን ይደግፋሉ።"</string>
<string name="role_browser_label" msgid="2877796144554070207">"ነባሪ አሳሽ መተግበሪያ"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"የአሳሽ መተግበሪያ"</string>
<string name="role_browser_description" msgid="3465253637499842671">"ወደ በየነ መረብ ለእርስዎ መዳረሻ የሚሰጥዎትን እና እርስዎ መታ የሚያደርጓቸውን አገናኞች የሚያሳዩ መተግበሪያዎች"</string>
@@ -404,9 +404,9 @@
<string name="request_role_current_default" msgid="738722892438247184">"አሁን ያለ ነባሪ"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"ዳግም አትጠይቅ"</string>
<string name="request_role_set_as_default" msgid="4253949643984172880">"እንደ ነባሪ አዘጋጅ"</string>
- <string name="phone_call_uses_microphone" msgid="233569591461187177">"ማይክሮፎን በ&lt;b&gt;ስልክ ጥሪ&lt;/b&gt; ላይ ስራ ላይ ውሏል"</string>
- <string name="phone_call_uses_microphone_and_camera" msgid="6291898755681748189">"ካሜራ እና ማይክሮፎን በ&lt;b&gt;ቪዲዮ ጥሪ&lt;/b&gt; ላይ ስራ ላይ ውለዋል"</string>
- <string name="phone_call_uses_camera" msgid="2048417022147857418">"ካሜራ በ&lt;b&gt;ቪዲዮ ጥሪ&lt;/b&gt; ላይ ስራ ላይ ውሏል"</string>
+ <string name="phone_call_uses_microphone" msgid="233569591461187177">"ማይክሮፎን በ&lt;b&gt;ስልክ ጥሪ&lt;/b&gt; ላይ ሥራ ላይ ውሏል"</string>
+ <string name="phone_call_uses_microphone_and_camera" msgid="6291898755681748189">"ካሜራ እና ማይክሮፎን በ&lt;b&gt;ቪዲዮ ጥሪ&lt;/b&gt; ላይ ሥራ ላይ ውለዋል"</string>
+ <string name="phone_call_uses_camera" msgid="2048417022147857418">"ካሜራ በ&lt;b&gt;ቪዲዮ ጥሪ&lt;/b&gt; ላይ ሥራ ላይ ውሏል"</string>
<string name="system_uses_microphone" msgid="576672130318877143">"ማይክሮፎን የሥርዓት አገልግሎትን በመጠቀም ተደርሶበታል"</string>
<string name="system_uses_microphone_and_camera" msgid="5124478304275138804">"ካሜራ እና ማይክሮፎን የሥርዓት አገልግሎትን በመጠቀም ተደርሶበታል"</string>
<string name="system_uses_camera" msgid="1911223105234441470">"ካሜራ የሥርዓት አገልግሎትን በመጠቀም ተደርሶበታል"</string>
@@ -436,8 +436,8 @@
<string name="no_special_app_access" msgid="6950277571805106247">"ምንም ልዩ መተግበሪያ መዳረሻ"</string>
<string name="special_app_access_no_apps" msgid="4102911722787886970">"መተግበሪያዎች የሉም"</string>
<string name="home_missing_work_profile_support" msgid="1756855847669387977">"የሥራ መገለጫን አይደግፍም"</string>
- <string name="encryption_unaware_confirmation_message" msgid="8274491794636402484">"ማስታወሻ፦ የእርስዎን መሣሪያ ዳግም ካስጀምሩ እና ማያ ገጽ መቆለፊያው እንዲቀናበር ካደረጉ፣ ይህ መተግበሪያ የእርስዎን መሣሪያ ዳግም እስከሚከፍቱ ድረስ መጀመር አይችልም።"</string>
- <string name="assistant_confirmation_message" msgid="7476540402884416212">"ረዳቱ በእርስዎ ስርዓት ላይ በአገልግሎት ላይ ስለሚውሉ መተግበሪያዎች መረጃን ማንበብ ይችላል፣ ይህም በእርስዎ ማያ ገጽ ላይ የሚታይ ወይም በመተግበሪያዎች ውስጥ የሚደረስበት መረጃን ይጨምራል።"</string>
+ <string name="encryption_unaware_confirmation_message" msgid="8274491794636402484">"ማስታወሻ፦ የእርስዎን መሣሪያ ዳግም ካስጀምሩ እና ማያ ገፅ መቆለፊያው እንዲቀናበር ካደረጉ፣ ይህ መተግበሪያ የእርስዎን መሣሪያ ዳግም እስከሚከፍቱ ድረስ መጀመር አይችልም።"</string>
+ <string name="assistant_confirmation_message" msgid="7476540402884416212">"ረዳቱ በእርስዎ ስርዓት ላይ በአገልግሎት ላይ ስለሚውሉ መተግበሪያዎች መረጃን ማንበብ ይችላል፣ ይህም በእርስዎ ማያ ገፅ ላይ የሚታይ ወይም በመተግበሪያዎች ውስጥ የሚደረስበት መረጃን ይጨምራል።"</string>
<string name="incident_report_channel_name" msgid="3144954065936288440">"ሳንካ ማረሚያ ውሂብን አጋራ"</string>
<string name="incident_report_notification_title" msgid="4635984625656519773">"ዝርዝር የሳንካ ማረሚያ መረጃ ይጋራ?"</string>
<string name="incident_report_notification_text" msgid="3376480583513587923">"<xliff:g id="APP_NAME">%1$s</xliff:g> የሳንካ ማረሚያ መረጃን መስቀል ይፈልጋል።"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"የረዳት ቀስቃሽ ማግኛን አሳይ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"የድምፅ ረዳትን ለማግበር ማይክራፎን ጥቅም ላይ ሲውል በሁናቴ አሞሌ ውስጥ አዶን አሳይ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በመሣሪያዎ ላይ ያሉ ፎቶዎችን፣ እና ማህደረ መረጃን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; እውቂያዎችዎን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የዚህ መሣሪያ አካባቢን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"መተግበሪያው እርስዎ ሲጠቀሙበት ብቻ ነው የአካባቢው መዳረሻ የሚኖረው"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የዚህ መሣሪያ አካባቢን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ይህ መተግበሪያ አካባቢዎን ሁልጊዜ መድረስ ሊፈልግ ይችላል፣ እርስዎ በማይጠቀሙበት ጊዜም እንኳ። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ"</annotation>"።"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"ለ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የመገኛ አካባቢ መዳረሻ ይለወጥ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ይህ መተግበሪያ አካባቢዎን ሁልጊዜ መድረስ ይፈልጋል፣ እርስዎ በማይጠቀሙበት ጊዜም እንኳ። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ"</annotation>"።"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በአቅራቢያ ያሉ የመሣሪያዎች አንጻራዊ አቀማመጥን እንዲፈልግ፣ እንዲገናኝ እና እንዲወስን ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በአቅራቢያ ያሉ የመሣሪያዎች አንጻራዊ አቀማመጥን እንዲፈልግ፣ እንዲገናኝ እና እንዲወስን ይፈቀድለት? "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"የ<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> አካባቢ መዳረሻ ከግምታዊ ወደ ትክክለኛ ይቀየር?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የዚህን መሣሪያ ግምታዊ አካባቢ እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ትክክለኛ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ግምታዊ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ቀን መቁጠሪያዎን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የኤስኤምኤስ መልዕክቶችን እንዲልክ እና እንዲመለከት ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በመሣሪያዎ ላይ ያሉ ፎቶዎችን፣ ማህደረ መረጃን እና ፋይሎችን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በመሣሪያዎ ላይ ያሉ &lt;b&gt;ፎቶዎችን፣ ቪዲዮዎችን፣ ሙዚቃን እና ኦዲዮን&lt;/b&gt; እንዲደርስ ይፈቀድለት?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በመሣሪያዎ ላይ ያሉ &lt;b&gt;ፎቶዎችን፣ ቪዲዮዎችን፣ ሙዚቃን፣ ኦዲዮን፣ ቪዲዮዎችን እና ሌሎች ፋይሎችን&lt;/b&gt; ዘንድ እንዲደርስ ይፈቀድለት?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በዚህ መሣሪያ ላይ ያለ ሙዚቃን እና ሌሎች የኦዲዮ ፋይሎችን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በዚህ መሣሪያ ላይ ያሉ ፎቶዎችን እና ቪዲዮዎችን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; በዚህ መሣሪያ ላይ ያሉ ፎቶዎችን እና ቪድዮዎችን እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ኦዲዮን እንዲቀዳ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"መተግበሪያው ኦዲዮን መቅዳት የሚችለው መተግበሪያውን እርስዎ ሲጠቀሙበት ብቻ ነው"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ኦዲዮን እንዲቀዳ ይፈቀድለት?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ይህ መተግበሪያ መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ሁልጊዜ ኦዲዮ መቅዳት ሊፈልግ ይችላል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"ለ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የማይክራፎን መዳረሻ ይለወጥ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ይህ መተግበሪያ መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ሁልጊዜ ኦዲዮ መቅዳት ይፈልጋል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የእርስዎን አካላዊ እንቅስቃሴ እንዲደርስበት ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ስዕሎችን እንዲያነሳ እና ቪዲዮን እንዲቀርጽ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"መተግበሪያው ስዕሎችን ማንሳት እና ቪዲዮውን መቅዳት የሚችለው መተግበሪያውን እርስዎ ሲጠቀሙበት ብቻ ነው"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ስዕሎችን እንዲያነሳ እና ቪዲዮን እንዲቀርጽ ይፈቀድለት?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ይህ መተግበሪያ መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ሁልጊዜ ሥዕሎችን ማንሳት እና ቪዲዮ መቅዳት ሊፈልግ ይችላል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"ለ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የካሜራ መዳረሻ ይለወጥ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ይህ መተግበሪያ መተግበሪያውን በማይጠቀሙበት ጊዜም እንኳ ሁልጊዜ ሥዕሎችን ማንሳት እና ቪዲዮ መቅዳት ይፈልጋል። "<annotation id="link">"በቅንብሮች ውስጥ ይፍቀዱ።"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"የእርስዎን ስልክ የጥሪ ምዝግብ ማስታወሻዎች &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; እንዲደርስበት ይፈቀድ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የስልክ ጥሪዎችን እንዲያደርግ እና እንዲያቀናብር ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; የሰውነትዎ መሠረታዊ ምልክቶች የዳሳሽ ውሂብ እንዲደርስ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"መተግበሪያውን በማይጠቀሙበት ጊዜ እንኳን ይህ መተግበሪያ የሰውነት ዳሳሽ ውሂብን ሁልጊዜ እንዲደርስ ለመፍቀድ "<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="auto_granted_permissions" msgid="6009452264824455892">"ቁጥጥር የሚደረግባችድው ፈቃዶች"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"መተግበሪያ ሥራ ላይ በሚውልበት ጊዜ የሰውነት ዳሳሽ ውሂብን እንዲደርስ ለ&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; መፍቀድ ይቀጥሉ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ለእርስዎ ማሳወቂያዎች እንዲልክ ይፈቀድለት?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"ቁጥጥር የሚደረግባችድው ፈቃዶች"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> የአካባቢ መዳረሻ አለው"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ድርጅትዎ <xliff:g id="APP_NAME">%1$s</xliff:g> አካባቢዎን እንዲደርስ ይፈቅዳል"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"ሌሎች ፍቃዶች"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"በስርዓት ጥቅም ላይ የሚውል ፈቃድ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"በስርዓት መተግበሪያዎችች ብቻ ጥቅም ላይ የሚውሉ ፈቃዶች።"</string>
@@ -546,14 +598,14 @@
<string name="remove_microphone_qs" msgid="1276551965129953198">"ለዚህ መተግበሪያ ፈቃድን አስወግድ"</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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> ስራ ላይ ውሏል"</string>
- <string name="active_app_usage_1_qs" msgid="4325136375823357052">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) ስራ ላይ እየዋለ ነው"</string>
- <string name="recent_app_usage_1_qs" msgid="261450184773310741">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) ስራ ላይ ውሏል"</string>
- <string name="active_app_usage_2_qs" msgid="6107866785243565283">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) ስራ ላይ እየዋለ ነው"</string>
- <string name="recent_app_usage_2_qs" msgid="3591205954235694403">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) ስራ ላይ ውሏል"</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>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> ሥራ ላይ ውሏል"</string>
+ <string name="active_app_usage_1_qs" msgid="4325136375823357052">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) ሥራ ላይ እየዋለ ነው"</string>
+ <string name="recent_app_usage_1_qs" msgid="261450184773310741">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) ሥራ ላይ ውሏል"</string>
+ <string name="active_app_usage_2_qs" msgid="6107866785243565283">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) ሥራ ላይ እየዋለ ነው"</string>
+ <string name="recent_app_usage_2_qs" msgid="3591205954235694403">"በቅርብ ጊዜ በ<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) ሥራ ላይ ውሏል"</string>
<string name="media_confirm_dialog_positive_button" msgid="9020793594051526399">"አረጋግጥ"</string>
<string name="media_confirm_dialog_negative_button" msgid="226987376924861785">"ተመለስ"</string>
<string name="media_confirm_dialog_title_a_to_p_aural_allow" msgid="8560601114044699903">"የሌሎች ፋይሎች መዳረሻም ይፈቀዳል"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ይህ መተግበሪያ የአካባቢ ውሂብን ከሦስተኛ ወገኖች ጋር ሊያጋራ እንደሚችል ገልጿል"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ውሂብ ማጋራት እና አካባቢ"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"የውሂብ ማጋራት መረጃ ከየት እንደሚመጣ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ገንቢው ይህ መተግበሪያ እንዴት ውሂብን እንደሚያጋራ ለዚህ የመሣሪያ አምራች መረጃን አቅርቧል። ገንቢው ይህን መረጃ በጊዜ ሂደት ሊያዘምን ይችላል።"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ገንቢው ይህ መተግበሪያ እንዴት ውሂብ እንደሚያጋራ መረጃ ለ"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" አቅርቧል። ገንቢው ይህን መረጃ በጊዜ ሂደት ሊያዘምን ይችላል።"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ይህ መተግበሪያ የአካባቢ ውሂብን ለሚከተሉት ሊያጋራ ይችላል፦"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"የውሂብ ማጋራት ይለያያል"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"የውሂብ ደህንነት"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"የአካባቢ ውሂብ ሊጋራ ይችላል"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ይህ መተግበሪያ የአካባቢ ውሂብዎን ከሦስተኛ ወገኖች ጋር ሊያጋራ እንደሚችል ገልጿል"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ይህን አገናኝ መክፈት አልተቻለም"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"የአካባቢ የውሂብ ማጋራት ዝማኔዎች"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"የእርስዎን የአካባቢ ውሂብ ሊያጋሩ የሚችሉበትን መንገድ የለወጡ መተግበሪያዎችን ይገምግሙ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"እነዚህ መተግበሪያዎች የእርስዎን የአካባቢ ውሂብ ሊያጋሩ የሚችሉበትን መንገድ ለውጠዋል። ከዚህ በፊት አጋርተውት ላይሆን ይችላል፣ ወይም አሁን ለማስታወቂያ ወይም የገበያ ሥራ ዓላማዎች ሊያጋሩት ይችላሉ።"</string>
diff --git a/PermissionController/res/values-ar-v33/strings.xml b/PermissionController/res/values-ar-v33/strings.xml
index bede64168..6b881f064 100644
--- a/PermissionController/res/values-ar-v33/strings.xml
+++ b/PermissionController/res/values-ar-v33/strings.xml
@@ -20,7 +20,7 @@
<string name="role_sms_request_description" msgid="1506966389698625395">"سيُسمح لهذا التطبيق بإرسال إشعارات إليك، وسيُمنح إذن الوصول إلى الكاميرا وجهات الاتصال والملفات والميكروفون والهاتف والرسائل القصيرة."</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"يمكن للتطبيقات التي لديها هذا الإذن الوصول إلى جميع الملفات على هذا الجهاز."</string>
<string name="work_policy_title" msgid="832967780713677409">"معلومات سياسة العمل"</string>
- <string name="work_policy_summary" msgid="3886113358084963931">"يتولى مشرف تكنولوجيا المعلومات إدارة الإعدادات."</string>
+ <string name="work_policy_summary" msgid="3886113358084963931">"يتولى مشرف تكنولوجيا المعلومات إدارة الإعدادات"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"توسيع القائمة وعرضها"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"تصغير القائمة وإخفاء الإعدادات"</string>
<string name="safety_center_entry_group_content_description" msgid="7048420958214443333">"قائمة <xliff:g id="ENTRY_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_SUMMARY">%2$s</xliff:g>"</string>
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"المزيد من التنبيهات"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"التنبيهات التي تم إغلاقها"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{التوسيع لعرض تنبيه واحد إضافي}zero{التوسيع لعرض # تنبيه إضافي}two{التوسيع لعرض تنبيهين إضافيَين}few{التوسيع لعرض # تنبيهات إضافية}many{التوسيع لعرض # تنبيهًا إضافيًا}other{التوسيع لعرض # تنبيه إضافي}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"تنبيه: <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"اكتمل الإجراء"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"التحقّق من الإعدادات التي يمكن أن تعزّز حماية جهازك"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"الإعدادات السريعة للأمان والخصوصية"</string>
diff --git a/PermissionController/res/values-ar-v34/strings.xml b/PermissionController/res/values-ar-v34/strings.xml
index 667db98f7..5a0d25e63 100644
--- a/PermissionController/res/values-ar-v34/strings.xml
+++ b/PermissionController/res/values-ar-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"الأمان والخصوصية"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"عناصر التحكّم"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"يمكنك إدارة وصول التطبيقات إلى البيانات الصحية."</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"إدارة إمكانية وصول التطبيقات إلى البيانات الصحية"</string>
<string name="location_settings" msgid="8863940440881290182">"الوصول إلى الموقع الجغرافي"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"للتطبيقات والخدمات: إذا كان هذا الخيار غير مفعّل، ستستمر إمكانية مشاركة بيانات الميكروفون عند الاتصال برقم طوارئ."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"للتطبيقات والخدمات"</string>
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index f1ecdc3c4..f74a4066c 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -43,7 +43,7 @@
<string name="permission_warning_template" msgid="2247087781222679458">"‏هل تريد السماح للتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإجراء <xliff:g id="ACTION">%2$s</xliff:g>؟"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"‏هل تريد السماح دائمًا للتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بهذا الإجراء <xliff:g id="ACTION">%2$s</xliff:g>؟"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"أثناء استخدام التطبيق فقط"</string>
- <string name="allow_permission_always" msgid="5194342531206054051">"دومًا"</string>
+ <string name="allow_permission_always" msgid="5194342531206054051">"دائمًا"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"عدم السماح وعدم طرح السؤال مرةً أخرى"</string>
<string name="permission_revoked_count" msgid="4785082705441547086">"<xliff:g id="COUNT">%1$d</xliff:g> إذن موقوف"</string>
<string name="permission_revoked_all" msgid="3397649017727222283">"كل الأذونات موقوفة."</string>
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{اليوم}=1{قبل يوم واحد}two{قبل يومَين}few{قبل # أيام}many{قبل # يومًا}other{قبل # يوم}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"إيقاف التطبيق"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"‏قد يؤدي إيقاف هذا التطبيق إلى عدم عمل نظام Android وتطبيقات أخرى على النحو المنشود. تجدر الإشارة إلى أنه لا يمكنك حذف هذا التطبيق لأنه من التطبيقات المثبّتة تلقائيًا على جهازك. ويعني إيقاف التطبيق أنه سيتم إيقافه وإخفاؤه على جهازك."</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"مدير الأذونات"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"إدارة الأذونات"</string>
<string name="never_ask_again" msgid="4728762438198560329">"عدم السؤال مجدّدًا"</string>
<string name="no_permissions" msgid="3881676756371148563">"ليس هناك أيّ أذونات."</string>
<string name="additional_permissions" msgid="5801285469338873430">"أذونات إضافية"</string>
@@ -129,7 +129,7 @@
<string name="permission_group_usage_title" msgid="2595013198075285173">"استخدام <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"عرض الأذونات الأخرى"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>، <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
- <string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g> و<xliff:g id="PERMGROUP_1">%2$s</xliff:g> و<xliff:g id="NUM">%3$s</xliff:g> تطبيق آخر"</string>
+ <string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"‫\"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>\" و\"<xliff:g id="PERMGROUP_1">%2$s</xliff:g>\" و<xliff:g id="NUM">%3$s</xliff:g> تطبيق آخر"</string>
<string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"المخطط الزمني لاستخدام <xliff:g id="PERMGROUP">%1$s</xliff:g> في آخر 24 ساعة"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"المخطط الزمني لاستخدام <xliff:g id="PERMGROUP">%1$s</xliff:g> في آخر 7 أيام"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"وقت استخدام هذا التطبيق لإذن <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
@@ -221,7 +221,7 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"التطبيقات غير المستخدمة"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"في حال عدم استخدام التطبيق لبضعة أشهر:\n\n• تتم إزالة الأذونات لحماية بياناتك.\n• يتم إيقاف الإشعارات لتوفير شحن البطارية.\n• تتم إزالة الملفات المؤقتة لتوفير مساحة.\n\nلمنح الأذونات والسماح للتطبيقات مرة أخرى، افتح التطبيق."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"في حال عدم استخدام تطبيق لمدة شهر:\n\n• تتم إزالة الأذونات لحماية بياناتك.\n• تتم إزالة الملفات المؤقتة لإخلاء بعض المساحة.\n\nللسماح بالأذونات مرة أخرى، افتَح التطبيق."</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{التطبيقات التي تم فتحها آخر مرة قبل أكثر من شهر واحد}zero{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهر}two{التطبيقات التي تم فتحها آخر مرة قبل أكثر من شهرَين}few{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهور}many{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهرًا}other{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهر}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{التطبيقات التي تم فتحها آخر مرة قبل أكثر من شهر واحد}zero{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهر}two{التطبيقات التي تم فتحها آخر مرة قبل أكثر من شهرَين}few{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # أشهر}many{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهرًا}other{التطبيقات التي تم فتحها آخر مرة قبل أكثر من # شهر}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"آخر مرة تم فتح التطبيق فيها: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"آخر مرة تم فتحه: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"في حال السماح لهذا التطبيق بإدارة كل الملفات، سيتمكن من الوصول إلى أي ملفات وتعديلها وحذفها من مساحة التخزين العادية على هذا الجهاز أو أجهزة التخزين المتصلة. يمكن أن يصل التطبيق إلى الملفات بدون طلب موافقتك."</string>
@@ -245,13 +245,13 @@
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"مرفوض حاليًا / تاريخ آخر وصول: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"لم يستخدم الإذن مطلقًا"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"تم الرفض / لم يسبق الحصول على الإذن"</string>
- <string name="allowed_header" msgid="7769277978004790414">"الأذونات المسموح بها"</string>
- <string name="allowed_always_header" msgid="6455903312589013545">"التطبيقات المسموح لها بالوصول طوال الوقت"</string>
+ <string name="allowed_header" msgid="7769277978004790414">"التطبيقات المسموح لها"</string>
+ <string name="allowed_always_header" msgid="6455903312589013545">"تطبيقات مسموح لها بالوصول طوال الوقت"</string>
<string name="allowed_foreground_header" msgid="6845655788447833353">"تطبيقات يمكنها الوصول عند استخدامها فقط"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"التطبيقات المسموح لها بالوصول إلى الوسائط فقط"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"التطبيقات المسموح لها بإدارة كل الملفات"</string>
<string name="ask_header" msgid="2633816846459944376">"الطلب في كل مرة"</string>
- <string name="denied_header" msgid="903209608358177654">"الأذونات غير المسموح بها"</string>
+ <string name="denied_header" msgid="903209608358177654">"التطبيقات غير المسموح لها"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"الاطّلاع على تطبيقات أكثر يمكنها الوصول إلى كل الملفات"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{يوم واحد}zero{# يوم}two{يومان}few{# أيام}many{# يومًا}other{# يوم}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{ساعة واحدة}zero{# ساعة}two{ساعتان}few{# ساعات}many{# ساعةً}other{# ساعة}}"</string>
@@ -340,7 +340,7 @@
<string name="no_apps_allowed" msgid="7718822655254468631">"لم يتم السماح لأي تطبيقات."</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"ما من تطبيقات تم منحها إذن الوصول إلى جميع الملفات."</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"ما من تطبيقات تم منحها إذن الوصول إلى الوسائط فقط."</string>
- <string name="no_apps_denied" msgid="7663435886986784743">"لم يتم رفض أي تطبيقات."</string>
+ <string name="no_apps_denied" msgid="7663435886986784743">"لم يتم رفض أي تطبيقات"</string>
<string name="car_permission_selected" msgid="180837028920791596">"مُختار"</string>
<string name="settings" msgid="5409109923158713323">"الإعدادات"</string>
<string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"تحظى خدمة <xliff:g id="SERVICE_NAME">%s</xliff:g> بوصول كامل إلى جهازك."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"عرض الرمز الخاص برصد تشغيل تطبيق مساعد"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"عرض الرمز في شريط الحالة عند استخدام الميكروفون لتفعيل المساعد الصوتي."</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالدخول إلى الصور والوسائط على جهازك؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى جهات الاتصال؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي لهذا الجهاز؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"لن يكون بإمكان التطبيق الوصول إلى الموقع الجغرافي إلا عند استخدامك لهذا التطبيق."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي لهذا الجهاز؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"قد يطلب هذا التطبيق الوصول الدائم إلى موقعك الجغرافي، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"‏هل تريد تغيير إمكانية الوصول إلى الموقع الجغرافي بالنسبة إلى &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;؟"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"يطلب هذا التطبيق الوصول الدائم إلى موقعك الجغرافي، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالعثور على الأجهزة المجاورة والربط بها وتحديد موضعها النسبي؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالعثور على الأجهزة المجاورة والربط بها وتحديد موضعها النسبي؟ "<annotation id="link">"يمكنك السماح بذلك في \"الإعدادات\"."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"هل تريد تغيير إذن وصول <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> من الموقع الجغرافي التقريبي إلى الموقع الجغرافي الدقيق؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي التقريبي لهذا الجهاز؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"دقيق"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"تقريبي"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى التقويم؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإرسال رسائل SMS وعرضها؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الصور والوسائط والملفات على جهازك؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"‏هل تسمح بوصول &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى &lt;b&gt;الصور والفيديوهات والموسيقى والملفات الصوتية&lt;/b&gt; على هذا الجهاز؟"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"‏هل تسمح بوصول &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى &lt;b&gt;الصور والفيديوهات والموسيقى والملفات الصوتية وملفات أخرى&lt;/b&gt; على هذا الجهاز؟"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"‏هل تريد السماح بوصول &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى المقاطع الموسيقية والملفات الصوتية على هذا الجهاز؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"‏هل تريد السماح بوصول &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى الصور والفيديوهات على هذا الجهاز؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‏هل تريد السماح بوصول تطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; إلى المزيد من الصور والفيديوهات على هذا الجهاز؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بتسجيل الصوت؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"لن يتمكن هذا التطبيق من تسجيل الصوت إلا عندما يكون قيد الاستخدام"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بتسجيل الصوت؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"قد يحتاج هذا التطبيق إلى تسجيل الصوت طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‏هل تريد تغيير إذن الوصول إلى الميكروفون بالنسبة إلى &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;؟"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"يحتاج هذا التطبيق إلى تسجيل الصوت طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"‏هل تريد السماح للتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى بيانات نشاطك البدني؟"</string>
- <string name="permgrouprequest_camera" msgid="5123097035410002594">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالتقاط صور وتسجيل فيديو؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
+ <string name="permgrouprequest_camera" msgid="5123097035410002594">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالتقاط صور وتسجيل فيديوهات؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"لن يتمكن هذا التطبيق من التقاط صور وتسجيل فيديوهات إلا عندما يكون قيد الاستخدام"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالتقاط صور وتسجيل فيديوهات؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"قد يحتاج هذا التطبيق إلى التقاط صور وتسجيل فيديوهات طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"‏هل تريد تغيير إذن الوصول إلى الكاميرا بالنسبة إلى &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;؟"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"يحتاج هذا التطبيق إلى التقاط صور وتسجيل فيديوهات طوال الوقت، حتى عند عدم استخدامك للتطبيق. يمكنك "<annotation id="link">"السماح بذلك في الإعدادات"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى سجلّ مكالماتك الهاتفية؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإجراء المكالمات الهاتفية وإدارتها؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى بيانات استشعار مؤشراتك الحيوية؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"للسماح لهذا التطبيق بالوصول إلى بيانات أجهزة استشعار الجسم دائمًا وحتى عند عدم استخدامك للتطبيق، "<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="auto_granted_permissions" msgid="6009452264824455892">"الأذونات خاضعة لتحكّم المشرف"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإرسال إشعارات إليك؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"الأذونات خاضعة لتحكّم المشرف"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"تطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" مسموح له بالوصول إلى الموقع الجغرافي"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"تسمح مؤسستك لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" بالوصول إلى موقعك الجغرافي."</string>
<string name="other_permissions_label" msgid="8986184335503271992">"الأذونات الأخرى"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"الأذونات المستخدمة من قِبل النظام"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"الأذونات المستخدمة من قِبل تطبيقات النظام فقط"</string>
@@ -549,7 +601,7 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"تم الاستخدام مؤخرًا من قِبل <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"تم الاستخدام مؤخرًا من قِبل \"<xliff:g id="APP_NAME">%1$s</xliff:g>\""</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"يتم الاستخدام من قِبل <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"تم الاستخدام مؤخرًا من قِبل <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"يتم الاستخدام من قِبل <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"بالنسبة للتطبيقات والخدمات. إذا كان هذا الخيار غير مفعّل، قد يظل بالإمكان مشاركة بيانات الميكروفون عند الاتصال برقم طوارئ."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"عرض التطبيقات والخدمات التي يمكنها الوصول إلى الموقع الجغرافي"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"عرض إشعار عند الوصول إلى الحافظة"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"عرض رسالة عندما يصل التطبيق إلى نص أو صور أو محتوى آخر تم نسخه."</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"عرض رسالة عندما يصل التطبيق إلى نص أو صور أو محتوى آخر تم نسخه"</string>
<string name="show_password_title" msgid="2877269286984684659">"عرض كلمات المرور"</string>
<string name="show_password_summary" msgid="1110166488865981610">"عرض الأحرف لفترة وجيزة أثناء الكتابة"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"وضَّح هذا التطبيق أنه يمكنه مشاركة بيانات الموقع الجغرافي مع جهات خارجية."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"مشاركة البيانات والموقع الجغرافي"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"من أين تأتي معلومات مشاركة البيانات؟"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"قدَّم المطوّر معلومات إلى الشركة المصنّعة لهذا الجهاز عن الطريقة التي يشارك بها هذا التطبيق البيانات. يمكن أنّ يعدّل المطوّر هذه المعلومات بمرور الوقت."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"‏قدَّم المطوّر معلومات إلى "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" عن كيفية مشاركة هذا التطبيق للبيانات. يمكن أنّ يعدّل المطوّر هذه المعلومات بمرور الوقت."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"قد يشارك التطبيق بيانات الموقع الجغرافي من أجل:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"اختلاف مشاركة البيانات"</string>
@@ -608,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"أمان البيانات"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"قد تتم مشاركة بيانات الموقع الجغرافي"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"وضَّح هذا التطبيق أنّه قد يشارك بيانات موقعك الجغرافي مع جهات خارجية."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"يتعذَّر فتح هذا الرابط"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"تعديلات مشاركة بيانات الموقع الجغرافي"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"راجِع التطبيقات التي غيّرت الطريقة التي قد تشارك بها بيانات موقعك الجغرافي."</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"مراجعة التطبيقات التي غيّرت الطريقة التي قد تشارك بها بيانات موقعك الجغرافي"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"غيّرت هذه التطبيقات الطريقة التي قد تشارك بها بيانات موقعك الجغرافي. ربما لم تشارك هذه التطبيقات بياناتك من قبل، أو قد تشاركها الآن لأغراض إعلانية أو تسويقية."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"قدَّم مطوّرو هذه التطبيقات معلومات حول الممارسات المتعلقة بمشاركة البيانات مع متجر التطبيقات. ويمكن أن يعدّلوا تلك المعلومات بمرور الوقت.\n\nقد تختلف الممارسات المتعلقة بمشاركة البيانات بناءً على إصدار تطبيقك وآلية استخدامك له ومنطقتك وعمرك."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"التعرّف على مشاركة البيانات"</string>
diff --git a/PermissionController/res/values-as/strings.xml b/PermissionController/res/values-as/strings.xml
index 40d8ed7c0..b1cd1b679 100644
--- a/PermissionController/res/values-as/strings.xml
+++ b/PermissionController/res/values-as/strings.xml
@@ -32,7 +32,7 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"“এপ্‌টো ব্যৱহাৰ হৈ থকা অৱস্থাত” ৰাখক"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“কেৱল এইবাৰৰ বাবে অনুমতি দিয়ক” বিকল্পটো ৰাখক"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"অধিক তথ্য"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"আটাইবোৰকে অনুমতি দিয়ক"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"আটাইবোৰৰে অনুমতি দিয়ক"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"আটাইবোৰকে সদায় অনুমতি দিয়ক"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"ফট’ আৰু ভিডিঅ’ বাছনি কৰক"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"অধিক বাছনি কৰক"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"অন্তিমবাৰ <xliff:g id="DATE">%s</xliff:g>ত খোলা হৈছিল"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"আপুনি যদি আটাইবোৰ ফাইল পৰিচালনাৰ অনুমতি দিয়ে, এই এপ্‌টোৱে এই ডিভাইচটোৰ যৌথ ষ্ট\'ৰেজত থকা যিকোনো ফাইল অথবা সংযুক্ত ষ্ট\'ৰেজ ডিভাইচসমূহ এক্সেছ কৰিব, সংশোধন কৰিব আৰু মচিব পাৰে। এপ্‌টোৱে আপোনাক নোসোধাকৈয়ে ফাইলসমূহ এক্সেছ কৰিব পাৰে।"</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"এই এপ্‌টোক ডিভাইচটোত থকা অথবা যিকোনো সংযুক্ত ষ্ট\'ৰেজ ডিভাইচসমূহৰ ফাইলসমূহ এক্সেছ কৰিবলৈ, সংশোধন কৰিবলৈ আৰু মচিবলৈ অনুমতি দিবনে? এই এপ্‌টোৱে আপোনাক নোসোধাকৈয়ে ফাইলসমূহ এক্সেছ কৰিব পাৰে।"</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"অনুমতি থকা এপ্‌সমূহে <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"অনুমতি থকা এপ্‌সমূহে কৰিব পাৰে: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"এই অনুমতিটো লাভ কৰা এপে আপোনাৰ শাৰীৰিক কাৰ্যকলাপ, যেনে খোজকঢ়া, বাইক চলোৱা, গাড়ী চলোৱা, পদক্ষেপৰ পৰিমাণ আৰু বহুতো তথ্য এক্সেছ কৰিব পাৰে"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"এই অনুমতি থকা এপ্‌সমূহে আপোনাৰ কেলেণ্ডাৰ এক্সেছ কৰিব পাৰে"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"এই অনুমতি থকা এপ্‌সমূহে ফ’ন কল লগ পঢ়িব আৰু লিখিব পাৰে"</string>
@@ -374,7 +374,7 @@
<string name="role_emergency_request_description" msgid="131645948770262850">"কোনো অনুমতিৰ প্ৰয়োজন নাই"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"বৰফ"</string>
<string name="role_home_label" msgid="3871847846649769412">"ডিফ’ল্ট হ’ম এপ্"</string>
- <string name="role_home_short_label" msgid="8544733747952272337">"হ’ম এপ্"</string>
+ <string name="role_home_short_label" msgid="8544733747952272337">"Home এপ্"</string>
<string name="role_home_description" msgid="7997371519626556675">"যিবোৰ এপক সাধাৰণতে লঞ্চাৰ বুলি কোৱা হয় সেই এপ্‌বোৰে আপোনাৰ Android ডিভাইচত গৃহ স্ক্ৰীনৰ ঠাই লয় আৰু আপোনাক নিজৰ ডিভাইচৰ সমল আৰু সুবিধাবোৰৰ এক্সেছ দিয়ে"</string>
<string name="role_home_request_title" msgid="738136983453341081">"<xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ ডিফ’ল্ট হ’ম এপ্ হিচাপে ছেট কৰিবনে?"</string>
<string name="role_home_request_description" msgid="2658833966716057673">"কোনো অনুমতিৰ প্ৰয়োজন নাই"</string>
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"সহায়কৰ ট্ৰিগাৰ চিনাক্তকৰণ দেখুৱাওক"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ভইচ এছিষ্টেণ্ট সক্ৰিয় কৰিবলৈ মাইক্ৰফ’ন ব্যৱহাৰ কৰিলে স্থিতি দণ্ডত দেখুৱাওক"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ ডিভাইচত থকা ফট’ আৰু মিডিয়া চাবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত থকা ফট’ আৰু মিডিয়া এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ সম্পৰ্কসূচী চাবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনাৰ সম্পৰ্কসমূহ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোৰ অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;ৰ অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"আপুনি এই এপ্ ব্যৱহাৰ কৰি থকাৰ সময়তহে ই আপোনাৰ অৱস্থান এক্সেছ কৰিব পাৰে"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোৰ অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>ৰ অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"এই এপ্‌টোৱে সকলো সময়তে আপোনাৰ অৱস্থান এক্সেছ কৰিবলৈ বিচাৰিব পাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকা সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে অৱস্থানৰ এক্সেছ সলনি কৰিবনে?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে অৱস্থানৰ এক্সেছ সলনি কৰিবনে?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"এই এপ্‌টোৱে সকলো সময়তে আপোনাৰ অৱস্থান এক্সেছ কৰিবলৈ বিচাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকা সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক বিচাৰিবলৈ, সংযোগ কৰিবলৈ আৰু নিকটৱৰ্তী ডিভাইচৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিবলৈ দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত নিকটৱৰ্তী ডিভাইচসমূহ বিচাৰিবলৈ, সংযোগ কৰিবলৈ আৰু সেইসমূহৰ প্ৰাসংগিক অৱস্থান নিৰ্ধাৰণ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক বিচাৰিবলৈ, সংযোগ কৰিবলৈ আৰু নিকটৱৰ্তী ডিভাইচৰ আপেক্ষিক স্থান নিৰ্ধাৰণ কৰিবলৈ দিবনে? "<annotation id="link">"ছেটিঙত অনুমতি প্ৰদান কৰক।"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>ৰ অৱস্থানৰ এক্সেছ আনুমানিকৰ পৰা সঠিকলৈ সলনি কৰিবনে?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>ৰ অৱস্থানৰ এক্সেছ আনুমানিকৰ পৰা সঠিকলৈ সলনি কৰিবনে?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোৰ আনুমানিক অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ৰ আনুমানিক অৱস্থান এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"সঠিক"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"আনুমানিক"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ কেলেণ্ডাৰ চাবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনাৰ কেলেণ্ডাৰ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এছএমএছ বাৰ্তা পঠিয়াবলৈ আৰু চাবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত এছএমএছ বাৰ্তা পঠিয়াবলৈ আৰু চাবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ ডিভাইচত থকা ফট\', মিডিয়া আৰু ফাইল চাবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত থকা ফট’ মিডিয়া আৰু ফাইল এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোত থকা &lt;b&gt;ফট’, ভিডিঅ’, সংগীত আৰু অডিঅ’&lt;/b&gt; এক্সেছ কৰিবলৈ দিবনে?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোত থকা &lt;b&gt;ফট’, ভিডিঅ’, সংগীত, অডিঅ’ আৰু অন্য ফাইল&lt;/b&gt; এক্সেছ কৰিবলৈ দিবনে?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোত থকা সংগীত আৰু অডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত থকা সংগীত আৰু অডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোত থকা ফট’ আৰু ভিডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত থকা ফট’ আৰু ভিডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এই ডিভাইচটোত থকা অধিক ফট’ আৰু ভিডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত থকা অধিক ফট’ আৰু ভিডিঅ’ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক অডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত অডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"আপুনি এই এপ্‌টো ব্যৱহাৰ কৰি থকাৰ সময়তহে কেৱল ই অডিঅ’ ৰেকৰ্ড কৰিব পাৰিব"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক অডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত অডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"এই এপ্‌টোৱে সকলো সময়তে অডিঅ’ ৰেকৰ্ড কৰিবলৈ বিচাৰিব পাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে মাই’ক্ৰ’নৰ এক্সেছ সলনি কৰিবনে?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে মাইক্ৰ’ফ’নৰ এক্সেছ সলনি কৰিবনে?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"এই এপ্‌টোৱে সকলো সময়তে অডিঅ’ ৰেকৰ্ড কৰিবলৈ বিচাৰিছে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"আপোনাৰ শাৰীৰিক কাৰ্যকলাপ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক এক্সেছ কৰাৰ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনাৰ শাৰীৰিক কাৰ্যকলাপ এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক ছবি তুলিবলৈ আৰু ভিডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"আপুনি এই এপ্‌টো ব্যৱহাৰ কৰি থকাৰ সময়তহে কেৱল ই ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিব পাৰিব।"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"এই এপ্‌টোৱে সকলো সময়তে ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিবলৈ বিচাৰিব পাৰে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে কেমেৰাৰ এক্সেছ সলনি কৰিবনে?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ৰ বাবে কেমেৰাৰ এক্সেছ সলনি কৰিবনে?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"এই এপ্‌টোৱে সকলো সময়তে ফট’ তুলিবলৈ আৰু ভিডিঅ’ ৰেকৰ্ড কৰিবলৈ বিচাৰিছে, আনকি আপুনি এপ্‌টো ব্যৱহাৰ কৰি নথকাৰ সময়তো। "<annotation id="link">"ছেটিঙত অনুমতি দিয়ক।"</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$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_device_aware_phone" msgid="4389610977195521813">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ বিষয়ে ছেন্সৰৰ ডেটা এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনাৰ দেহৰ গুৰুত্বপূৰ্ণ অংগসমূহৰ বিষয়ে ছেন্সৰৰ ডেটা এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"এই এপ্‌টোক আপুনি এইটো ব্যৱহাৰ কৰি নথকা সময়কো ধৰি সকলো সময়তে শৰীৰৰ ছেন্সৰৰ ডেটা এক্সেছ কৰিবলৈ দিবলৈ, "<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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"এপ্‌টো ব্যৱহাৰ কৰি থকাৰ সময়ত &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক আপোনাৰ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ত আপোনালৈ জাননী পঠিয়াবলৈ অনুমতি দিবনে?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"নিয়ন্ত্ৰিত অনুমতিসমূহ"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ অৱস্থানৰ এক্সেছ আছে"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"আপোনাৰ প্ৰতিষ্ঠানে <xliff:g id="APP_NAME">%1$s</xliff:g>ক আপোনাৰ অৱস্থান এক্সেছ কৰাৰ অনুমতি দিয়ে"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"এই এপ্‌টোৱে তৃতীয় পক্ষৰ সৈতে অৱস্থানৰ ডেটা শ্বেয়াৰ কৰিব পাৰে বুলি জনাইছে"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ডেটা শ্বেয়াৰ কৰা আৰু অৱস্থান"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ডেটা শ্বেয়াৰ কৰাৰ তথ্যখিনি ক’ৰ পৰা আহে"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"এই এপ্‌টোৱে কেনেকৈ ডেটা শ্বেয়াৰ কৰে সেই বিষয়ে বিকাশকৰ্তাই নিৰ্মাতাক তথ্য দিছে। বিকাশকৰ্তাগৰাকীয়ে এই তথ্যখিনি সময়ৰ লগে লগে আপডে’ট কৰিব পাৰে।"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"এই এপ্‌টোৱে কেনেকৈ ডেটা শ্বেয়াৰ কৰে সেই বিষয়ে বিকাশকৰ্তাই "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"ক তথ্য দিছে। বিকাশকৰ্তাগৰাকীয়ে এই তথ্যখিনি সময়ৰ লগে লগে আপডে’ট কৰিব পাৰে।"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"এপ্‌টোৱে ইয়াৰ বাবে অৱস্থানৰ ডেটা শ্বেয়াৰ কৰিব পাৰে:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ডেটা শ্বেয়াৰ কৰা কার্যটো ভিন্ন হয়"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ডেটা সুৰক্ষা"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"অৱস্থানৰ ডেটা শ্বেয়াৰ কৰা হ’ব পাৰে"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"এই এপ্‌টোৱে তৃতীয় পক্ষৰ সৈতে আপোনাৰ অৱস্থানৰ ডেটা শ্বেয়াৰ কৰিব পাৰে বুলি জনাইছে"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"এই লিংকটো খুলিব নোৱাৰি"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"অৱস্থানৰ বাবে ডেটা শ্বেয়াৰ কৰাৰ আপডে’ট"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"আপোনাৰ অৱস্থানৰ ডেটা শ্বেয়াৰ কৰিব পৰাৰ ধৰণসমূহ সলনি কৰা এপ্‌সমূহ পৰ্যালোচনা কৰক"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"এই এপ্‌সমূহে আপোনাৰ অৱস্থানৰ ডেটা শ্বেয়াৰ কৰিব পৰাৰ ধৰণসমূহ সলনি কৰিছে। সেইবোৰে পূৰ্বে এয়া শ্বেয়াৰ নকৰিব পাৰে অথবা এতিয়া বিজ্ঞাপন অথবা মাৰ্কেটিঙৰ উদ্দেশ্যে শ্বেয়াৰ কৰিব পাৰে।"</string>
diff --git a/PermissionController/res/values-az-v33/strings.xml b/PermissionController/res/values-az-v33/strings.xml
index c14a9cf99..da3e73e74 100644
--- a/PermissionController/res/values-az-v33/strings.xml
+++ b/PermissionController/res/values-az-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Daha çox siqnal"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Qapadılmış xəbərdarlıqlar"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Genişləndirin və daha bir xəbərdarlığa baxın}other{Genişləndirin və daha # xəbərdarlığa baxın}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Xəbərdarlıq. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Əməliyyat tamamlandı"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Cihazınıza qoruma əlavə edə biləcək ayarları yoxlayın"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Güvənlik və məxfilik sürətli ayarları"</string>
diff --git a/PermissionController/res/values-az/strings.xml b/PermissionController/res/values-az/strings.xml
index ee102d1ad..c99db9760 100644
--- a/PermissionController/res/values-az/strings.xml
+++ b/PermissionController/res/values-az/strings.xml
@@ -41,7 +41,7 @@
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"İmtina edin"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə <xliff:g id="ACTION">%2$s</xliff:g> fəaliyyəti üçün icazə verilsin?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin <xliff:g id="ACTION">%2$s</xliff:g> əməliyyatına daima icazə verilsin?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin <xliff:g id="ACTION">%2$s</xliff:g> fəaliyyətinə hər zaman icazə verilsin?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Ancaq tətbiq istifadəsi zamanı"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Həmişə"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"İcazə verməyin və bir daha soruşmayın"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Assistent aktivasiya aşkarlanmasını göstərin"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mikrofonun istifadəsi zamanı səsli yardımı aktiv etmək üçün status panelində ikonanı göstərin"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin cihazdakı foto və mediaya daxil olmasına icazə verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə kontaktlara daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə bu cihazın məkanına daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Tətbiq yalnız ondan istifadə etiyiniz zaman məkanı əldə edə bilər"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə bu cihazın məkanına daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə məkanınıza daxil olmaq istəyə bilər. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; üçün məkana giriş dəyişdirilsin?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə məkanınıza daxil olmaq istəyir. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə yaxınlıqdakı cihazları tapmaq, qoşulmaq və nisbi mövqeyini təyin etmək icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə yaxınlıqdakı cihazları tapmaq, qoşulmaq və nisbi mövqeyini təyin etmək icazəsi verilsin? "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> tətbiqinin məkan girişi təxminidən dəqiqə dəyişdirilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə bu cihazın təxmini məkanına daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Dəqiq"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Təxmini"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə təqvimə daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə SMS mesajları göndərmək və onlara baxmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə cihazdakı foto, media və fayllara daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin bu cihazdakı &lt;b&gt;foto, video, musiqi və audiolara&lt;/b&gt; girişinə icazə verilsin?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin bu cihazdakı &lt;b&gt;foto, video, musiqi, audio və digər fayllara&lt;/b&gt; girişinə icazə verilsin?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə bu cihazdakı musiqi və audioya girişinə icazə verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin cihazdakı foto və videolara girişinə icazə verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə bu cihazda digər foto və videolara daxil olmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə səs yazmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Tətbiq yalnız ondan istifadə etiyiniz zaman audio yaza biləcək"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə audio yazmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə audio yazmaq istəyə bilər. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; üçün mikrofona giriş dəyişdirilsin?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə audio yazmaq istəyir. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin fiziki fəaliyyətinizə daxil olmasına icazə verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə şəkil və video çəkmək icazəsi verilsin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Tətbiq yalnız ondan istifadə etiyiniz zaman şəkil çəkə və video yaza biləcək"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə şəkil çəkmək və video yazmaq icazəsi verilsin?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə şəkil çəkmək və video yazmaq istəyə bilər. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; üçün kameraya giriş dəyişdirilsin?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Bu tətbiq hətta ondan istifadə etmədiyiniz zaman belə şəkil çəkmək və video yazmaq istəyir. "<annotation id="link">"Ayarlarda icazə verin."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"İdarə edilən icazələr"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"İdarə edilən icazələr"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinin məkan icazəsi var"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Təşkilat <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqinə məkan icazəsi verir"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Digər icazələr"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Sistem tərəfindən istifadə edilən icazə"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Yalnız sistem tətbiqləri tərəfindən istifadə edilən icazələr."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Bu tətbiq məkan datasını üçüncü tərəflərlə paylaşa biləcəyini bildirib"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Data paylaşımı və məkan"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Data paylaşma məlumatı haradan əldə edilir"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Developer bu tətbiqin datanı paylaşması haqqında cihaz istehsalçısına məlumat verib. Developer bu məlumatı vaxtaşırı yeniləyə bilər."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Developer tətbiqin datanı necə paylaşması haqqında məlumatı bu ünvana təqdim edib: "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Developer bu məlumatı vaxtaşırı yeniləyə bilər."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Tətbiq bunun üçün məkan datasını paylaşa bilər:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Data paylaşma dəyişə bilər"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Data təhlükəsizliyi"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Məkan datası paylaşıla bilər"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Bu tətbiq məkan datasını üçüncü tərəflərlə paylaşa biləcəyini bildirib"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Bu linki açmaq olmur"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Məkan üzrə data paylaşma yenilikləri"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Məkan datasını paylaşma üsulunu dəyişən tətbiqləri nəzərdən keçirin"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Bu tətbiqlər məkan datasını paylaşma üsulunu dəyişib. Ola bilsin ki, onu daha öncə paylaşmayıblar və ya indi reklam, yaxud marketinq məqsədləri üçün paylaşırlar."</string>
diff --git a/PermissionController/res/values-b+sr+Latn-v33/strings.xml b/PermissionController/res/values-b+sr+Latn-v33/strings.xml
index c3ec0e10d..acc79ac84 100644
--- a/PermissionController/res/values-b+sr+Latn-v33/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Još obaveštenja"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Odbačena obaveštenja"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Proširite i vidite još jedno obaveštenje}one{Proširite i vidite još # obaveštenje}few{Proširite i vidite još # obaveštenja}other{Proširite i vidite još # obaveštenja}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Obaveštenje. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Radnja je dovršena"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Proverite podešavanja koja mogu da dodaju zaštitu uređaju"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Brza podešavanja bezbednosti i privatnosti"</string>
diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml
index f66592c90..0eb27c9c7 100644
--- a/PermissionController/res/values-b+sr+Latn/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Uvek dozvoli sve"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Izaberite slike i video snimke"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Izaberite još"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ne biraj više"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ništa više"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ionako ne dozvoli"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Odbaci"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Dozvoli uvek"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dozv. samo dok se apl. koristi"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dozvoli samo dok se apl. koristi"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Ne dozvoli"</string>
<string name="loading" msgid="4789365003890741082">"Učitava se…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Sve dozvole"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Poslednji put otvoreno: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ako omogućite upravljanje svim datotekama, ova aplikacija može da pristupa svim datotekama u zajedničkom memorijskom prostoru na ovom uređaju ili povezanim uređajima za skladištenje i da menja i briše te datoteke. Aplikacija može da pristupa datotekama bez pitanja."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Želite li da dozvolite da ova aplikacija pristupa datotekama na uređaju ili svim povezanim uređajima za skladištenje i da menja i briše te datoteke? Ova aplikacija može da pristupa datotekama bez pitanja."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije sa ovom dozvolom mogu <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije sa tom dozvolom imaju ove mogućnosti: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Aplikacije sa ovom dozvolom mogu da pristupaju podacima o fizičkim aktivnostima, poput hodanja, vožnje bicikla, vožnje automobila, broja koraka i drugo"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Aplikacije sa ovom dozvolom mogu da pristupaju kalendaru"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Aplikacije sa ovom dozvolom mogu da čitaju i dodaju stavke u evidenciju poziva na telefonu"</string>
@@ -397,7 +397,7 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i pristup dozvolama za telefon, SMS poruke, kontakte i kalendar."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> će dobiti dozvolu za interakciju sa obaveštenjima i strimovanje aplikacija na povezanom uređaju."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Ova usluga deli slike, medijski sadržaj i obaveštenja sa telefona na drugim uređajima."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"Podrazumevana aplik za beleške"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"Podrazumevana apl. za beleške"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Aplikacija za beleške"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Aplikacije koje vam omogućavaju da pravite beleške na uređaju"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"beleške"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Prikazuj otkrivanje aktiviranja pomoćnika"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Prikazuje ikonu na statusnoj traci kada se mikrofon koristi za aktiviranje glasovnog pomoćnika"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Želite li da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa slikama i medijima na uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa kontaktima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacija će imati pristup lokaciji samo dok koristite aplikaciju"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ova aplikacija možda želi da pristupa lokaciji sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Želite li da promenite pristup lokaciji za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ova aplikacija želi da pristupa lokaciji sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Dozvoljavate da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pronalazi uređaje u blizini, povezuje se s njima i određuje im relativan položaj?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Dozvoljavate da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pronalazi uređaje u blizini, povezuje se s njima i određuje im relativan položaj? "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Želite li da promenite pristup aplikacije <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> iz približne lokacije na preciznu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa približnoj lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precizna"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Približna"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa kalendaru?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; šalje i pregleda SMS-ove?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa slikama, medijskim i drugim fajlovima na uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Pristup &lt;b&gt;slikama, videu, muzici i zvuku&lt;/b&gt; na uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Pristup slikama, videu, muzici, zvuku i drugom na uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Dozvoljavate li pristup muzici i zvuku na ovom uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Dozvoljavate li pristup slikama i videu na ovom uređaju za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Dozvoljavate li da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa i drugim slikama i video snimcima na ovom uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima zvuk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacija će moći da snima zvuk samo dok koristite aplikaciju"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima zvuk?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ova aplikacija možda želi da snima zvuk sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Želite da promenite pristup mikrofonu za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ova aplikacija želi da snima zvuk sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Želite li da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa fizičkim aktivnostima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima slike i video snimke?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacija će moći da snima slike i video snimke samo dok koristite aplikaciju"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Želite da dozvolite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima slike i video snimke?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ova aplikacija možda želi da snima slike i video snimke sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Želite da promenite pristup kameri za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ova aplikacija želi da snima slike i video snimke sve vreme, čak i kada ne koristite aplikaciju. "<annotation id="link">"Dozvolite u podešavanjima."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrolisane dozvole"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolisane dozvole"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ima pristup lokaciji"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organizacija dozvoljava da <xliff:g id="APP_NAME">%1$s</xliff:g> pristupa lokaciji"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Druge dozvole"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Dozvole koje koristi sistem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Dozvole koje koriste samo sistemske aplikacije."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ova aplikacija navodi da može da deli podatke sa trećim stranama"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Deljenje podataka i lokacija"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Odakle informacije o deljenju podataka potiču"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Programer je naveo informacije proizvođaču ovog uređaja o tome kako ova aplikacija deli podatke. Programer može vremenom da ažurira ove podatke."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Programer je naveo informacije o tome kako ova aplikacija deli podatke za:"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Programer može vremenom da ažurira ove podatke."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ova aplikacija može da deli podatke o lokaciji za:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Deljenje podataka varira"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Bezbednost podataka"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Podaci o lokaciji mogu da se dele"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ova aplikacija navodi da može da deli podatke o lokaciji sa trećim stranama"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Ne možemo da otvorimo ovaj link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Ažuriranja deljenja podataka za lokaciju"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Pregledajte aplikacije koje su promenile način na koji mogu da dele podatke o lokaciji"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Aplikacije su promenile način na koji mogu da dele podatke o lokaciji. Možda ih nisu delile ranije ili ih sada dele u svrhe oglašavanja ili marketinga."</string>
diff --git a/PermissionController/res/values-be-v33/strings.xml b/PermissionController/res/values-be-v33/strings.xml
index 9d5fbc9af..511ed49c6 100644
--- a/PermissionController/res/values-be-v33/strings.xml
+++ b/PermissionController/res/values-be-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Іншыя абвесткі"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Адхіленыя абвесткі"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Разгарніце, каб убачыць яшчэ адну абвестку}one{Разгарніце, каб убачыць яшчэ # абвестку}few{Разгарніце, каб убачыць яшчэ # абвесткі}many{Разгарніце, каб убачыць яшчэ # абвестак}other{Разгарніце, каб убачыць яшчэ # абвесткі}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Абвестка. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Дзеянне завершана"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Праверце налады, якія могуць павысіць бяспеку вашай прылады"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Хуткія налады бяспекі і прыватнасці"</string>
diff --git a/PermissionController/res/values-be/strings.xml b/PermissionController/res/values-be/strings.xml
index fa54a396b..9c2e2044d 100644
--- a/PermissionController/res/values-be/strings.xml
+++ b/PermissionController/res/values-be/strings.xml
@@ -40,7 +40,7 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Усё роўна не дазваляць"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Адхіліць"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Дазволіць &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"Заўсёды дазваляць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Толькі пры актыўнай праграме"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Заўсёды"</string>
@@ -49,12 +49,12 @@
<string name="permission_revoked_all" msgid="3397649017727222283">"усе адключаны"</string>
<string name="permission_revoked_none" msgid="9213345075484381180">"няма адключаных"</string>
<string name="grant_dialog_button_allow" msgid="5314677880021102550">"Дазволіць"</string>
- <string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"Дазволіць заўсёды"</string>
+ <string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"Дазваляць заўсёды"</string>
<string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"Падчас выкарыстання праграмы"</string>
<string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Пераключыцца на дакладнае вызначэнне месцазнаходжання"</string>
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"Пакінуць прыблізнае месцазнаходжанне"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"Толькі ў гэты раз"</string>
- <string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Дазволіць заўсёды"</string>
+ <string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Дазваляць заўсёды"</string>
<string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"Дазволіць кіраванне ўсімі файламі"</string>
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"Дазволіць доступ да файлаў мультымедыя"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Праграмы"</string>
@@ -107,7 +107,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:0 (1351721623256561996) -->
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
- <string name="permission_access_always" msgid="1474641821883823446">"Дазволіць заўсёды"</string>
+ <string name="permission_access_always" msgid="1474641821883823446">"Дазваляць заўсёды"</string>
<string name="permission_access_only_foreground" msgid="7801170728159326195">"Падчас карыстання праграмай"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Не дазваляць"</string>
<string name="loading" msgid="4789365003890741082">"Загрузка…"</string>
@@ -186,8 +186,8 @@
<string name="app_permission_button_allow" msgid="5808039516494774647">"Дазволіць"</string>
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Дазволіць кіраванне ўсімі файламі"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Дазволіць доступ толькі да мультымедыя"</string>
- <string name="app_permission_button_allow_always" msgid="4573292371734011171">"Дазволіць заўсёды"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Дазволіць толькі падчас карыстання праграмай"</string>
+ <string name="app_permission_button_allow_always" msgid="4573292371734011171">"Дазваляць заўсёды"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Дазваляць толькі падчас карыстання праграмай"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Заўсёды дазваляць усе"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Заўсёды пытацца"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Не дазваляць"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Адкрывалася ў апошні раз <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Калі вы дазволіце кіраванне ўсімі файламі, гэта праграма зможа атрымліваць доступ да ўсіх файлаў у агульным сховішчы на гэтай прыладзе ці ў сховішчах падключаных прылад, а таксама змяняць і выдаляць гэтыя файлы. Праграма зможа атрымліваць доступ да файлаў без вашага ведама."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Дазволіць гэтай праграме атрымліваць доступ да файлаў на гэтай прыладзе і ў любых падключаных сховішчах, а такама змяняць і выдаляць файлы? Гэта праграма зможа атрымліваць доступ да файлаў без вашага ведама."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Характарыстыка дазволу: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Праграмы з гэтым дазволам могуць <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Праграмы з такім дазволам могуць мець доступ да звестак пра вашу фізічную актыўнасць, напрыклад перамяшчэнні пешшу, язду на веласіпедзе, на аўтамабілі, колькасць крокаў і многае іншае"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Праграмы з гэтым дазволам могуць мець доступ да календара"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Праграмы з гэтым дазволам могуць чытаць журнал выклікаў тэлефона і дадаваць у яго запісы"</string>
@@ -251,7 +251,7 @@
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Дазволены доступ толькі да мультымедыя"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Дазволена кіраванне ўсімі файламі"</string>
<string name="ask_header" msgid="2633816846459944376">"Заўсёды пытацца"</string>
- <string name="denied_header" msgid="903209608358177654">"Забаронена"</string>
+ <string name="denied_header" msgid="903209608358177654">"Забароненыя"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"Праглядзець іншыя праграмы, якія маюць доступ да ўсіх файлаў"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 дзень}one{# дзень}few{# дні}many{# дзён}other{# дня}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# гадзіна}one{# гадзіна}few{# гадзіны}many{# гадзін}other{# гадзіны}}"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Паказваць значок актывацыі памочніка"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Паказваць значок на панэлі стану, калі мікрафон выкарыстоўваецца для актывацыі галасавога памочніка"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да фота і мультымедыя на вашай прыладзе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да вашых кантактаў?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да звестак пра месцазнаходжанне гэтай прылады?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Праграма будзе мець доступ да звестак пра месцазнаходжанне толькі падчас карыстання ёю"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да звестак пра месцазнаходжанне гэтай прылады?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Гэта праграма можа запытваць пастаянны доступ да звестак пра ваша месцазнаходжанне, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Змяніць налады доступу да даных пра месцазнаходжанне для праграмы &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Гэта праграма запытвае пастаянны доступ да звестак пра ваша месцазнаходжанне, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; знаходзіць прылады паблізу, падключацца да іх і вызначаць адлегласць да іх?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; знаходзіць прылады паблізу, падключацца да іх і вызначаць адлегласць да такіх прылад? "<annotation id="link">"Дазволіць у наладах."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Памяняць у доступах праграмы \"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\" прыблізнае месцазнаходжанне на дакладнае?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да звестак пра прыблізнае месцазнаходжанне гэтай прылады?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Дакладна"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Прыблізна"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да вашага календара?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; адпраўляць і праглядаць SMS-паведамленні?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да фота, мультымедыя і файлаў на вашай прыладзе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да &lt;b&gt;фота, відэа, музыкі і аўдыяфайлаў&lt;/b&gt; на гэтай прыладзе?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да &lt;b&gt;фота, відэа, музыкі, аўдыя і файлаў&lt;/b&gt; на гэтай прыладзе?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да музыкі і аўдыя на гэтай прыладзе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да фота і відэа на гэтай прыладзе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да дадатковых фота і відэа на гэтай прыладзе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; запісваць аўдыя?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Гэта праграма зможа запісваць аўдыя толькі падчас яе выкарыстання"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; запісваць аўдыя?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Гэта праграма можа запісваць аўдыя ўвесь час, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Змяніць налады доступу да мікрафона для праграмы &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Гэта праграма запытвае дазвол запісваць аўдыя ўвесь час, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных фізічнай актыўнасці?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; рабіць фота і запісваць відэа?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Гэта праграма зможа рабіць фота і запісваць відэа толькі падчас яе выкарыстання"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; рабіць фота і запісваць відэа?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Гэта праграма можа рабіць фота і запісваць відэа ўвесь час, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Змяніць налады доступу да камеры для праграмы &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Гэта праграма запытвае дазвол рабіць фота і запісваць відэа ўвесь час, нават калі яна не выкарыстоўваецца. "<annotation id="link">"Дайце дазвол у наладах."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да журналаў выклікаў вашага тэлефона?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; рабіць тэлефонныя выклікі і кіраваць імі?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ да даных з датчыкаў пра вашы асноўныя фізіялагічныя паказчыкі?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Каб дазволіць гэтай праграме мець пастаянны доступ да даных датчыкаў цела, нават калі яна не выкарыстоўваецца, "<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="auto_granted_permissions" msgid="6009452264824455892">"Кіраваныя дазволы"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; адпраўляць вам апавяшчэнні?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Кіраваныя дазволы"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" мае доступ да даных геалакацыі"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Ваша арганізацыя дазволіла праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" мець доступ да вашага месцазнаходжання"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Iншыя дазволы"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Дазвол, які выкарыстоўваецца сістэмай"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Дазволы, якія выкарыстоўваюцца толькі сістэмнымі праграмамі."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Гэта праграма можа абагульваць даныя пра месцазнаходжанне з трэцімі бакамі"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Абагульванне даных і даныя пра месцазнаходжанне"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Адкуль бярэцца інфармацыя пра абагульванне даных"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Распрацоўшчык перадаў вытворцы прылады інфармацыю пра тое, як гэтая праграма абагульвае даныя. З цягам часу гэта інфармацыя можа быць зменена распрацоўшчыкам."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Распрацоўшчык дадаў (сюды: "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>") інфармацыю пра тое, як гэтая праграма абагульвае даныя. З цягам часу гэтая інфармацыя можа быць зменена распрацоўшчыкам."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Праграма можа абагульваць геаданыя для наступнага:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Абагульванне даных залежыць ад розных умоў"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Бяспека даных"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Дазвол на абагульванне даных пра месцазнаходжанне"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Гэта праграма можа абагульваць даныя пра месцазнаходжанне з трэцімі бакамі"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Не ўдалося адкрыць гэтую спасылку"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Змяненні ў абагульванні даных пра месцазнаходжанне"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Праглядзець праграмы, для якіх быў зменены спосаб абагульвання даных пра месцазнаходжанне"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Для гэтых праграм спосаб абагульвання даных пра месцазнаходжанне змяніўся. Магчыма, яны раней увогуле не абагульвалі такія даныя альбо цяпер пачалі іх абагульваць у мэтах рэкламы ці маркетынгу."</string>
diff --git a/PermissionController/res/values-bg-v33/strings.xml b/PermissionController/res/values-bg-v33/strings.xml
index d93187d03..6080b29b8 100644
--- a/PermissionController/res/values-bg-v33/strings.xml
+++ b/PermissionController/res/values-bg-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Още сигнали"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Отхвърлени сигнали"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Разгънете и вижте още един сигнал}other{Разгънете и вижте още # сигнала}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Сигнал. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Действието е завършено"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Проверете настройките, които могат да подобрят защитата на устройството ви"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Бързи настройки за сигурността и поверителността"</string>
diff --git a/PermissionController/res/values-bg/strings.xml b/PermissionController/res/values-bg/strings.xml
index 8b7f76a6a..8405142a4 100644
--- a/PermissionController/res/values-bg/strings.xml
+++ b/PermissionController/res/values-bg/strings.xml
@@ -126,11 +126,11 @@
<string name="app_name_unknown" msgid="1319665005754048952">"Неизвестно"</string>
<string name="permission_usage_title" msgid="1568233336351734538">"Управление на поверителността"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Преглед на приложенията, които наскоро са използвали разрешения"</string>
- <string name="permission_group_usage_title" msgid="2595013198075285173">"Използване на <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
+ <string name="permission_group_usage_title" msgid="2595013198075285173">"Използване на: <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Вижте други разрешения"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> и още <xliff:g id="NUM">%3$s</xliff:g>"</string>
- <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Хронология за използването на <xliff:g id="PERMGROUP">%1$s</xliff:g> от приложенията през последните 24 часа"</string>
+ <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Хронология за използването на „<xliff:g id="PERMGROUP">%1$s</xliff:g>“ от приложенията през последните 24 часа"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"Хронология за използването на <xliff:g id="PERMGROUP">%1$s</xliff:g> от приложенията през последните 7 дни"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"Кога това приложение е използвало разрешението за достъп до <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="permission_usage_access_dialog_learn_more" msgid="7121468469493184613">"Научете повече"</string>
@@ -197,7 +197,7 @@
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Когато точното местоположение е изключено, приложенията могат да осъществяват достъп до приблизителното ви местоположение"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Разрешение за: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Достъп до „<xliff:g id="PERM">%1$s</xliff:g>“ за това приложение"</string>
- <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Преглед на всички разрешения, предоставени за <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <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>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Последно отваряне на <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ако разрешите управлението на всички файлове, това приложение може да осъществява достъп до, да променя и изтрива всички файлове в стандартното хранилище на устройството или в свързаните хранилища. Приложението може да осъществява достъп до файловете, без да ви пита."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Да се разреши ли на това приложение да осъществява достъп до, да променя и изтрива файлове на устройството или в свързаните хранилища? Приложението може да осъществява достъп до файловете, без да ви пита."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Приложенията с това разрешение могат да осъществяват <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Приложенията с това разрешение могат да <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Приложенията с това разрешение имат достъп до физическата ви активност, като например ходене, колоездене, шофиране, брой крачки и др."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Приложенията с това разрешение имат достъп до календара ви"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Приложенията с това разрешение могат да четат списъка с телефонните обаждания и да записват в него"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Показване на икона за готовност на асистент"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Показване на икона в лентата на състоянието, когато микрофонът се използва за активиране на гласовия асистент"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да има достъп до снимките и мултимедията на устройството ви?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до контактите ви?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до местоположението на това устройство?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Само когато използвате приложението, то ще има достъп до местоположението"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до местоположението на това устройство?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Това приложение може да иска да осъществява постоянен достъп до местоположението ви – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Да се промени ли достъпът до местоположението за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Това приложение иска да осъществява постоянен достъп до местоположението ви – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да намира у-ва в близост, да се свързва с тях и да определя относит. им позиция?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да намира у-ва в близост, да се свързва с тях и да определя относит. им позиция? "<annotation id="link">"Разрешаване от настройките"</annotation>"."</string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Да се промени ли достъпът на <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> от приблизително местоположение на точно?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до приблизителното местоположение на това устройство?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Точно"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Приблизително"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до календара ви?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да изпраща и преглежда SMS съобщения?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да има достъп до снимките, мултимедията и файловете на устройството ви?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Разрешаване на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; достъп до &lt;b&gt;снимките, видео- и аудиосъдържанието&lt;/b&gt; на устройството ви?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Разр. на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; достъп до &lt;b&gt;снимките, видео- и аудиосъдърж. и другите файлове&lt;/b&gt; на у-вото?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до музиката и аудиофайловете на това устройство?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до снимките и видеоклиповете на това устройство?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до още снимки и видеоклипове на това устройство?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да записва аудио?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Приложението ще може да записва аудио само когато го използвате"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да записва аудио?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Това приложение може да иска да записва аудио по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Да се промени ли достъпът до микрофона за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Това приложение иска да записва аудио по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до физическата ви активност?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да прави снимки и да записва видеоклипове?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Приложението ще може да прави снимки и записва видеоклипове само когато го използвате"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да прави снимки и да записва видеоклипове?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Това приложение може да иска да прави снимки и да записва видеоклипове по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Да се промени ли достъпът до камерата за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Това приложение иска да прави снимки и да записва видеоклипове по всяко време – дори когато не го използвате. "<annotation id="link">"Разрешете от настройките."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до списъците с телефонните ви обаждания?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да извършва и управлява телефонни обаждания?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да осъществява достъп до данните от сензорите за жизнените ви показатели?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"За да разрешите на това приложение да осъществява достъп до данните от сензорите за тяло по всяко време – дори когато не го използвате, "<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="auto_granted_permissions" msgid="6009452264824455892">"Контролирани разрешения"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да ви изпраща известия?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Контролирани разрешения"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> има достъп до местоположението"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Организацията ви разрешава на <xliff:g id="APP_NAME">%1$s</xliff:g> да осъществява достъп до местоположението ви"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Други разрешения"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Разрешения, използвани от системата"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Разрешения, които се използват само от системните приложения."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Това приложение посочи, че може да споделя с трети страни данни за местоположението"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Споделяне на данни и достъп до местоположението"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Източници на информацията за споделянето на данни"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Програмистът предостави на производителя на това устройство информация за начина, по който приложението споделя данни. Програмистът може да актуализира съответната информация с течение на времето."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Програмистът предостави на "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" информация за начина, по който това приложение споделя данни. Програмистът може да актуализира съответната информация с течение на времето."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Това прил. може да споделя данни за местоп. с цел:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Споделянето на данни варира"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Безопасност на данните"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Възможно е да бъдат споделяни данни за местоположението"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Това приложение посочи, че може да споделя с трети страни данни за местоположението ви"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Тази връзка не може да се отвори"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Актуализации за споделянето на данни за местоположението"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Прегледайте приложенията, променили начина, по който могат да споделят данни за местоположението ви"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Тези приложения са променили начина, по който могат да споделят данни за местоположението ви. Може да не са ги споделяли преди или вече да го правят с рекламни или маркетингови цели."</string>
diff --git a/PermissionController/res/values-bn-v33/strings.xml b/PermissionController/res/values-bn-v33/strings.xml
index 28c18f23a..6bef7e90d 100644
--- a/PermissionController/res/values-bn-v33/strings.xml
+++ b/PermissionController/res/values-bn-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"আরও সতর্কতা"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"বাতিল করা সতর্কতা"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{বড় করুন ও আরও একটি সতর্কতা দেখুন}one{বড় করুন ও আরও #টি সতর্কতা দেখুন}other{বড় করুন ও আরও #টি সতর্কতা দেখুন}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"সতর্কতা। <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"অ্যাকশন সম্পূর্ণ হয়েছে"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"আপনার ডিভাইসকে আরও সুরক্ষিত করতে পারে এমন সেটিংস দেখুন"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"সুরক্ষা ও গোপনীয়তা সংক্রান্ত দ্রুত সেটিংস"</string>
diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml
index f87e4303d..120314a79 100644
--- a/PermissionController/res/values-bn/strings.xml
+++ b/PermissionController/res/values-bn/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"যাই হোক, অনুমতি দেবেন না"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"বাতিল করুন"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>টির মধ্যে <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> নম্বর"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপটিকে <xliff:g id="ACTION">%2$s</xliff:g> করার অনুমতি দেবেন?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপটিকে সব সময় <xliff:g id="ACTION">%2$s</xliff:g> করার অনুমতি দেবেন?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপটিকে এটি করার অনুমতি দেবেন?: <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপটিকে সব সময় এটি করার অনুমতি দেবেন?: <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"শুধুমাত্র অ্যাপ ব্যবহার করার সময়"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"সব সময়"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"অনুমতি দেবেন না এবং আর জিজ্ঞাসা করবেন না"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"অ্যাসিস্ট্যান্ট ট্রিগার ডিটেকশন দেখুন"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ভয়েস অ্যাসিস্ট্যান্ট চালু করতে মাইক্রোফোন ব্যবহার হলে স্ট্যাটাস বারে আইকন দেখায়"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ডিভাইসের ফটো এবং মিডিয়াতে অ্যাক্সেস দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার পরিচিতিতে অ্যাক্সেস দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"আপনি এই অ্যাপ ব্যবহার করার সময়েই শুধু সেটি আপনার লোকেশন অ্যাক্সেস করতে পারবে"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এই ডিভাইসের লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"এই অ্যাপ হয়ত সবসময় আপনার লোকেশন অ্যাক্সেস করতে চায়, এমনকি আপনার অ্যাপ চালু না থাকলেও। "<annotation id="link">"সেটিংস বিকল্প থেকে অনুমতি দিন।"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-এর জন্য লোকেশন অ্যাক্সেস পরিবর্তন করতে চান?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"এই অ্যাপটি সবসময় আপনার লোকেশন অ্যাক্সেস করতে চায়, এমনকি আপনার অ্যাপ চালু না থাকলেও। "<annotation id="link">"সেটিংস বিকল্প থেকে অনুমতি দিন।"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"কাছাকাছি ডিভাইস খুঁজে দেখতে, কানেক্ট করতে এবং সেটির আপেক্ষিক অবস্থান নির্ধারণ করতে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"কাছাকাছি ডিভাইস খুঁজে দেখতে, কানেক্ট করতে এবং সেটির আপেক্ষিক অবস্থান নির্ধারণ করতে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে অনুমতি দেবেন? "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>-এ লোকেশন অ্যাক্সেস, আনুমানিক থেকে সুনির্দিষ্ট লোকেশনে পরিবর্তন করতে চান?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এই ডিভাইসের নিকটবর্তী লোকেশন অ্যাক্সেস করতে দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"নির্ভুল"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"নিকটবর্তী"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ক্যালেন্ডারে অ্যাক্সেস দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে এসএমএস দেখতে ও পাঠাতে দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ডিভাইসের ফটো, মিডিয়া এবং ফাইলে অ্যাক্সেস দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"এই ডিভাইসে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে &lt;b&gt;ফটো, ভিডিও, মিউজিক এবং অডিও&lt;/b&gt; অ্যাক্সেসের অনুমতি দেবেন?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"এই ডিভাইসে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে &lt;b&gt;ফটো, ভিডিও, মিউজিক, অডিও ও অন্যান্য ফাইল&lt;/b&gt; অ্যাক্সেসের অনুমতি দেবেন?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"এই ডিভাইসে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে মিউজিক ও অডিও ফাইল অ্যাক্সেসের অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"এই ডিভাইসে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে ফটো ও ভিডিও অ্যাক্সেসের অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"এই ডিভাইসে &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আরও ফটো ও ভিডিও অ্যাক্সেসের অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অডিও রেকর্ড করার অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"আপনি এই অ্যাপ ব্যবহার করার সময়েই শুধুমাত্র সেটি অডিও রেকর্ড করতে পারবে"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অডিও রেকর্ড করার অনুমতি দিতে চান?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"এই অ্যাপ হয়ত সবসময় এমনকি আপনি যখন অ্যাপ ব্যবহার করছেন না তখনও অডিও রেকর্ড করতে চাইতে পারে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-এর জন্য মাইক্রোফোন অ্যাক্সেস পরিবর্তন করতে চান?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"এই অ্যাপ হয়ত সবসময় এমনকি আপনি যখন অ্যাপ ব্যবহার করছেন না তখনও অডিও রেকর্ড করতে চাইবে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার শারীরিক অ্যাক্টিভিটি অ্যাক্সেস করার অনুমতি দিতে চান?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে ফটো তোলা ও ভিডিও রেকর্ড করার অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"আপনি এই অ্যাপ ব্যবহার করার সময়েই শুধুমাত্র সেটি ছবি তুলতে এবং ভিডিও রেকর্ড করতে পারবে"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; অ্যাপকে ফটো তুলতে এবং ভিডিও রেকর্ড করার অনুমতি দিতে চান?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"এই অ্যাপ হয়ত সবসময় এমনকি আপনি যখন অ্যাপ ব্যবহার করছেন না তখনও ছবি তুলতে এবং ভিডিও রেকর্ড করতে চাইতে পারে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-এর জন্য ক্যামেরা অ্যাক্সেস পরিবর্তন করতে চান?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"এই অ্যাপ সবসময় এমনকি আপনি যখন অ্যাপ ব্যবহার করছেন না তখনও ছবি তুলতে এবং ভিডিও রেকর্ড করতে চাইবে। "<annotation id="link">"সেটিংস থেকে অনুমতি দিন।"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে আপনার ফোন কল লগ অ্যাক্সেস করার অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে কল করতে এবং কল পরিচালনা করতে দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে সেন্সর থেকে আপনার ভাইটাল সাইনের ডেটা অ্যাক্সেস করতে দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"অ্যাপটি ব্যবহার না করলেও, সেটিকে সবসময় বডি সেন্সর ডেটাতে অ্যাক্সেস দিতে "<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="auto_granted_permissions" msgid="6009452264824455892">"নিয়ন্ত্রিত অনুমতি"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে বিজ্ঞপ্তি পাঠানোর অনুমতি দেবেন?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"নিয়ন্ত্রিত অনুমতি"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর লোকেশন অ্যাক্সেস আছে"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"আপনার সংস্থা <xliff:g id="APP_NAME">%1$s</xliff:g>-কে আপনার লোকেশন অ্যাক্সেস করার অনুমতি দেয়"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"অন্যান্য অনুমতি"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"যেসব অনুমতি শুধু সিস্টেম অ্যাপ ব্যবহার করেছে"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"যেসব অনুমতি শুধুমাত্র সিস্টেম অ্যাপ্লিকেশনে ব্যবহার করা হয়।"</string>
@@ -577,20 +629,21 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"ব্যাকগ্রাউন্ডে লোকেশন অ্যাক্সেস করার অনুমতি আছে এমন অ্যাপ পর্যালোচনা করুন"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"এই অ্যাপ সব সময় আপনার লোকেশন অ্যাক্সেস করতে পারে, এমনকি অ্যাপটি বন্ধ করা থাকলেও।\n\nসঠিকভাবে কাজ করার জন্য কিছু সুরক্ষা ও জরুরি অ্যাপকে ব্যাকগ্রাউন্ডে আপনার লোকেশন অ্যাক্সেস করতে দিতে হবে।"</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"অ্যাক্সেস পরিবর্তন করা হয়েছে"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"সম্প্রতি লোকেশন ব্যবহার সম্পর্কিত তথ্য দেখুন"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"লোকেশন ব্যবহারের সাম্প্রতিক তথ্য দেখুন"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"গোপনীয়তা নিয়ন্ত্রণ"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"ক্যামেরা অ্যাক্সেস"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"মাইক্রোফোনে অ্যাক্সেস"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"অ্যাপ ও পরিষেবার জন্য"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"অ্যাপ ও পরিষেবার জন্য। এই সেটিং বন্ধ থাকলেও, মাইক্রোফোনের ডেটা শেয়ার করা যেতে পারে। আপনি কোনও জরুরি নম্বরে কল করলে এমন হতে পারে।"</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"লোকেশনে অ্যাক্সেস রয়েছে এমন অ্যাপ ও পরিষেবা দেখা"</string>
- <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ক্লিপবোর্ড অ্যাক্সেস দেখায়"</string>
+ <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ক্লিপবোর্ড অ্যাক্সেস সংক্রান্ত তথ্য দেখানো"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"আপনার কপি করা টেক্সট, ছবি বা অন্যান্য কন্টেন্ট অ্যাপ অ্যাক্সেস করলে মেসেজ দেখায়"</string>
<string name="show_password_title" msgid="2877269286984684659">"পাসওয়ার্ড দেখুন"</string>
<string name="show_password_summary" msgid="1110166488865981610">"টাইপ করার সময় অক্ষরগুলি কয়েক মুহূর্তের জন্য দেখুন"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"এই অ্যাপ, থার্ড-পার্টির সাথে লোকেশন ডেটা শেয়ার করার অনুমতি চাইতে পারে"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ডেটা শেয়ারিং ও লোকেশন"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ডেটা শেয়ারিং সম্পর্কিত তথ্য কোথা থেকে পাওয়া যায়"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"কীভাবে এই অ্যাপ ডেটা শেয়ার করে তার ব্যাপারে ডেভেলপার ডিভাইসের প্রস্তুতকারককে তথ্য প্রদান করেছে। ভবিষ্যতে ডেভেলপার এই তথ্য আপডেট করতে পারে।"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"কীভাবে এই অ্যাপ ডেটা শেয়ার করে, তার ব্যাপারে ডেভেলপার "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"-কে তথ্য প্রদান করেছে। ভবিষ্যতে ডেভেলপার এই তথ্য আপডেট করতে পারে।"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"এই অ্যাপ যে জন্য লোকেশন ডেটা শেয়ার করতে পারে:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ডেটা শেয়ারিংয়ের ক্ষেত্রে হওয়া পরিবর্তন"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ডেটা সুরক্ষা"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"লোকেশন ডেটা শেয়ার করা হতে পারে"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"এই অ্যাপ জানিয়েছে যে, এটি থার্ড পার্টির সাথে আপনার লোকেশন ডেটা শেয়ার করতে পারে"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"এই লিঙ্কটি খুলতে পারা যাচ্ছে না"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"লোকেশনের জন্য ডেটা শেয়ারিং সম্পর্কিত আপডেট"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"যেসব অ্যাপ আপনার লোকেশন ডেটা শেয়ার করার উপায়ের ক্ষেত্রে পরিবর্তন করেছে, সেগুলি পর্যালোচনা করুন"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"এইসব অ্যাপ আপনার লোকেশন ডেটা শেয়ার করার উপায়ের ক্ষেত্রে পরিবর্তন করেছে। এগুলি আগে হয়ত শেয়ার করেনি অথবা এখন বিজ্ঞাপন বা মার্কেটিং সংক্রান্ত উদ্দেশ্যে শেয়ার করতে পারে।"</string>
diff --git a/PermissionController/res/values-bs-television/strings.xml b/PermissionController/res/values-bs-television/strings.xml
index 997588205..117b35bd5 100644
--- a/PermissionController/res/values-bs-television/strings.xml
+++ b/PermissionController/res/values-bs-television/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="grant_dialog_button_deny_dont_ask_again" msgid="747769682501286250">"Odbij i ne pitaj ponovo"</string>
- <string name="grant_dialog_how_to_change" msgid="997462845048160559">"Ovo možete kasnije promijeniti u odjeljku Postavke i Aplikacije"</string>
+ <string name="grant_dialog_how_to_change" msgid="997462845048160559">"Ovo možete kasnije promijeniti u odjeljku Postavke &gt; Aplikacije"</string>
<string name="current_permission_template" msgid="6240787325714651204">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="preference_show_system_apps" msgid="4262140518693221093">"Prikaži sistemske aplikacije"</string>
<string name="app_permissions_decor_title" msgid="7438716722786036814">"Odobrenja za aplikaciju"</string>
diff --git a/PermissionController/res/values-bs-v33/strings.xml b/PermissionController/res/values-bs-v33/strings.xml
index 4df792c5e..598dc6a6c 100644
--- a/PermissionController/res/values-bs-v33/strings.xml
+++ b/PermissionController/res/values-bs-v33/strings.xml
@@ -40,7 +40,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Prebaci. <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g>. <xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Uključi/isključi"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Otvori"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Pregledaj postavke"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Pregledajte postavke"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Postavke"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Informacije"</string>
</resources>
diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml
index cd722859d..b6b729e22 100644
--- a/PermissionController/res/values-bs/strings.xml
+++ b/PermissionController/res/values-bs/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Svejedno nemoj dozvoliti"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Odbaci"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Želite li dozvoliti da aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uradi sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Uvijek dozvoliti da aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uradi sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da uradi sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Uvijek dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da uradi sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Samo dok se koristi aplikacija"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Uvijek"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Nemoj dozvoliti i ne pitaj ponovo"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Dozvoli sve vrijeme"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dozvoli samo dok se koristi"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dozvoli samo dok se aplikacija koristi"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Nemoj dozvoliti"</string>
<string name="loading" msgid="4789365003890741082">"Učitavanje…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Sva odobrenja"</string>
@@ -226,20 +226,20 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Posljednji put otvoreno na dan <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ako dozvolite upravljanje svim fajlovima, ova aplikacija može pristupati, mijenjati i brisati sve fajlove u zajedničkoj pohrani na ovom uređaju ili na povezanim uređajima za pohranu. Aplikacija može pristupati fajlovima bez prethodnog pitanja."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Dozvoliti ovoj aplikaciji da pristupa, mijenja i briše fajlove na uređaju ili na svim povezanim uređajima za pohranu? Ova aplikacija može pristupati fajlovima bez prethodnog pitanja."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije s ovim odobrenjem mogu <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije s ovim odobrenjem mogu raditi sljedeće: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Aplikacije s ovim odobrenjem mogu pristupiti informacijama o vašim fizičkim aktivnostima kao što su hodanje, vožnja bicikla, vožnja, broj koraka i još mnogo toga"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Aplikacije s ovim odobrenjem mogu pristupiti vašem kalendaru"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Aplikacije s ovim odobrenjem mogu čitati i pisati zapisnike telefonskih poziva"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"Aplikacije s ovim odobrenjem mogu snimati fotografije i videozapise"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"Aplikacije s ovim odobrenjem mogu pristupiti vašim kontaktima"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Aplikacije s ovim odobrenjem mogu pristupiti lokaciji uređaja"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Aplikacije s ovim odobrenjem mogu pristupati lokaciji uređaja"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Aplikacije s ovim odobrenjem mogu pronaći uređaje u blizini, povezati se s njima te odrediti njihov relativni položaj"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"Aplikacije s ovim odobrenjem mogu snimati zvuk"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"Aplikacije s ovim odobrenjem mogu upućivati pozive i upravljati njima"</string>
<string name="permission_description_summary_sensors" msgid="1836045815643119949">"Aplikacije s ovim odobrenjem mogu pristupiti podacima senzora o vašim vitalnim znakovima"</string>
<string name="permission_description_summary_sms" msgid="725999468547768517">"Aplikacije s ovim odobrenjem mogu slati i pregledati SMS poruke"</string>
<string name="permission_description_summary_storage" msgid="6575759089065303346">"Aplikacije s ovim odobrenjem mogu pristupiti fotografijama, medijima i drugim fajlovima na vašem uređaju"</string>
- <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Aplikacije s ovim odobrenjem mogu pristupiti muzičkim i drugim audio fajlovima na ovom uređaju"</string>
+ <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Aplikacije s ovim odobrenjem mogu pristupati muzičkim i drugim audio fajlovima na ovom uređaju"</string>
<string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Aplikacije s ovim odobrenjem mogu pristupiti fotografijama i videozapisima na ovom uređaju"</string>
<string name="app_permission_most_recent_summary" msgid="4292074449384040590">"Posljednji pristup: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Trenutno odbijeno/posljednji pristup: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Prikaži otkrivanje aktiviranja asistenta"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Prikaz ikone na statusnoj traci kada se mikrofon koristi za aktiviranje glasovne pomoći"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa fotografijama i medijima na vašem uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa vašim kontaktima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacija će imati pristup lokaciji isključivo dok je koristite"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Moguće je da će aplikacija željeti pristup vašoj lokaciji sve vrijeme, čak i kada je ne budete koristili. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Promijeniti pristup lokaciji za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ova aplikacija želi pristup vašoj lokaciji sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pronađe uređaje u blizini, poveže se s njima te odredi njihov relativni položaj?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pronađe uređaje u blizini, poveže se s njima te odredi njihov relativni položaj? "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Promijeniti pristup aplikacije <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> lokaciji iz približne u tačnu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa približnoj lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Tačno"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Približno"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupi vašem kalendaru?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da šalje i pregleda SMS poruke?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa fotografijama, medijima i fajlovima na vašem uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Dozvoliti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa &lt;b&gt;foto/video/muzičkim/audio fajlovima&lt;/b&gt; na ovom uređaju?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Dozvoliti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa &lt;b&gt;foto/video/muzičkim/audio i drugim fajlovima&lt;/b&gt; na uređaju?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Dozvoliti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa muzici i zvuku na ovom uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa fotografijama i videozapisima na ovom uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa većem broju fotografija i videozapisa na uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima zvuk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacija će moći snimati zvuk samo za vrijeme korištenja"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snimanje zvuka?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ova aplikacija može tražiti da snima zvuk sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Promijeniti pristup mikrofonu za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ova aplikacija traži da snima zvuk sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa informacijama o vašoj fizičkoj aktivnosti?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima fotografije i videozapise?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacija će moći snimati slike i videozapise samo za vrijeme korištenja"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snimanje slika i videozapisa?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ova aplikacija može tražiti da snima slike i videozapise sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Promijeniti pristup kameri za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ova aplikacija traži da snima slike i videozapise sve vrijeme, čak i kada je ne koristite. "<annotation id="link">"Dozvolite u postavkama."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa senzornim podacima o vašim vitalnim znakovima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Da dozvolite aplikaciji da pristupa 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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolirana odobrenja"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ima pristup lokaciji"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Vaša organizacija dozvoljava aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> da pristupa vašoj lokaciji"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Aplikacija je navela da može dijeliti podatke o lokaciji s trećim stranama"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Dijeljenje podataka i lokacija"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Odakle dolaze informacije o dijeljenju podataka"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Programer je proizvođaču uređaja naveo informacije o tome kako ova aplikacija dijeli podatke. Programer može povremeno ažurirati ove informacije."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Programer je usluzi "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" naveo informacije o tome kako ova aplikacija dijeli podatke. Programer može tokom vremena ažurirati ove informacije."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Aplikacija može dijeliti podatke o lokaciji za:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Dijeljenje podataka se razlikuje"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Sigurnost podataka"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Podaci o lokaciji se mogu dijeliti"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Aplikacija je navela da može dijeliti podatke o lokaciji s trećim stranama"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Nije moguće otvoriti ovu vezu"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Promjene u dijeljenju podataka za lokaciju"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Pregledajte aplikacije koje su promijenile način na koji mogu dijeliti podatke o lokaciji"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ove aplikacije su promijenile način na koji mogu dijeliti podatke o lokaciji. Možda ih prije nisu dijelile ili ih sada dijele u svrhe oglašavanja ili marketinga."</string>
diff --git a/PermissionController/res/values-ca-v33/strings.xml b/PermissionController/res/values-ca-v33/strings.xml
index 60ca34dc3..0526fffbc 100644
--- a/PermissionController/res/values-ca-v33/strings.xml
+++ b/PermissionController/res/values-ca-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Més alertes"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertes ignorades"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Desplega i consulta 1 alerta més}many{Desplega i consulta # alertes més}other{Desplega i consulta # alertes més}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Acció completa"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Comprova les opcions de configuració que puguin afegir protecció al dispositiu"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Configuració ràpida de la seguretat i la privadesa"</string>
diff --git a/PermissionController/res/values-ca-v34/strings.xml b/PermissionController/res/values-ca-v34/strings.xml
index 651a36b0b..8aad7b657 100644
--- a/PermissionController/res/values-ca-v34/strings.xml
+++ b/PermissionController/res/values-ca-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Seguretat i privadesa"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Controls"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Salut connectada"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Gestiona l\'accés de l\'aplicació a les dades de salut"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Gestiona l\'accés de les aplicacions a les dades de salut"</string>
<string name="location_settings" msgid="8863940440881290182">"Accés a la ubicació"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Per a aplicacions i serveis. Si aquesta opció de configuració està desactivada, és possible que les dades del micròfon es continuïn compartint quan truquis a un número d\'emergència."</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Per a aplicacions i serveis. És possible que les dades del micròfon es comparteixin si truques a un número d\'emergència encara que aquesta opció estigui desactivada."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Per a aplicacions i serveis"</string>
</resources>
diff --git a/PermissionController/res/values-ca/strings.xml b/PermissionController/res/values-ca/strings.xml
index 23df40f90..f6213d3a3 100644
--- a/PermissionController/res/values-ca/strings.xml
+++ b/PermissionController/res/values-ca/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"No permetis de cap manera"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Ignora"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Vols permetre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Vols permetre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Permetre sempre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permetre sempre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Només mentre s\'utilitzi l\'aplicació"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Sempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"No permetis i no m\'ho tornis a preguntar"</string>
@@ -51,7 +51,7 @@
<string name="grant_dialog_button_allow" msgid="5314677880021102550">"Permet"</string>
<string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"Permet sempre"</string>
<string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"Mentre s\'utilitza l\'aplicació"</string>
- <string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Canvia a la ubicació exacta"</string>
+ <string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Canvia a la ubicació precisa"</string>
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"Mantén la ubicació aproximada"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"Només aquesta vegada"</string>
<string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Permet sempre"</string>
@@ -191,16 +191,16 @@
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Permet sempre tot"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Pregunta sempre"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"No permetis"</string>
- <string name="precise_image_description" msgid="6349638632303619872">"Ubicació exacta"</string>
+ <string name="precise_image_description" msgid="6349638632303619872">"Ubicació precisa"</string>
<string name="approximate_image_description" msgid="938803699637069884">"Ubicació aproximada"</string>
- <string name="app_permission_location_accuracy" msgid="7166912915040018669">"Utilitza la ubicació exacta"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Quan la ubicació exacta està desactivada, les aplicacions poden accedir a la teva ubicació aproximada"</string>
+ <string name="app_permission_location_accuracy" msgid="7166912915040018669">"Utilitza la ubicació precisa"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Quan la ubicació precisa està desactivada, les aplicacions poden accedir a la teva ubicació aproximada"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Permís d\'accés a <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Accés a <xliff:g id="PERM">%1$s</xliff:g> per a aquesta aplicació"</string>
<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="unused_apps_category_title" msgid="2988455616845243901">"Configuració d\'aplicació no utilitzada"</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>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"Activitat a l\'app en pausa si no s\'usa"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Oberta per darrera vegada el dia <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Si permets la gestió de tots els fitxers, aquesta aplicació podrà accedir als fitxers, així com modificar-los i suprimir-los, que es trobin a l\'emmagatzematge comú d\'aquest dispositiu o als dispositius d\'emmagatzematge connectats. L\'aplicació podrà accedir als fitxers sense demanar-te permís."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Vols permetre que aquesta aplicació accedeixi als fitxers, o els modifiqui o suprimeixi, en aquest dispositiu o en qualsevol altre dispositiu d\'emmagatzematge connectat? Aquesta aplicació podrà accedir als fitxers sense demanar-te permís."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Les aplicacions amb aquest permís poden <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Les aplicacions amb aquest permís poden fer el següent: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Les aplicacions amb aquest permís poden accedir a la teva activitat física, com ara els passejos a peu, els trajectes amb bici o cotxe, el recompte de passos, etc."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Les aplicacions amb aquest permís poden accedir al teu calendari"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Les aplicacions amb aquest permís poden llegir i editar el registre de trucades del telèfon"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostra la detecció d\'activador de l\'assistent"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostra una icona a la barra d\'estat quan s\'utilitzi el micròfon per activar l\'assistent de veu"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les fotos i al contingut multimèdia del dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi als contactes?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la ubicació del dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"L\'aplicació només tindrà accés a la ubicació quan l\'estiguis utilitzant"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la ubicació del dispositiu?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Aquesta aplicació vol tenir accés a la teva ubicació sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a Configuració"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vols canviar l\'accés a la ubicació per a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aquesta aplicació vol tenir accés a la teva ubicació sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a Configuració"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; cerqui els dispositius propers, s\'hi connecti i en determini la posició relativa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; cerqui els dispositius propers, s\'hi connecti i en determini la posició relativa? "<annotation id="link">"Permet a Configuració"</annotation>"."</string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Vols canviar l\'accés a la ubicació que té <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> d\'aproximada a exacta?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la ubicació aproximada del dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exacta"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi al calendari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; enviï i llegeixi missatges SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a fotos, contingut multimèdia i fitxers del dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi als &lt;b&gt;vídeos, fotos, música i àudio&lt;/b&gt; del dispositiu?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi als &lt;b&gt;vídeos, fotos, música, àudio i altres fitxers&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la música i l\'àudio d\'aquest dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a les fotos i els vídeos d\'aquest dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a més fotos i vídeos d\'aquest dispositiu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gravi àudio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"L\'aplicació només podrà gravar àudio mentre l\'estiguis utilitzant"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gravi àudio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"És possible que aquesta aplicació vulgui gravar àudio sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a la configuració"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vols canviar l\'accés al micròfon de l\'aplicació &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Aquesta aplicació vol gravar àudio sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a la configuració"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; accedeixi a la teva activitat física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; faci fotos i gravi vídeos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"L\'aplicació només podrà fer fotos i gravar vídeos mentre l\'estiguis utilitzant"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; faci fotos i gravi vídeos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"És possible que aquesta app vulgui fer fotos i gravar vídeos sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a la configuració"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vols canviar l\'accés a la càmera de l\'aplicació &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Aquesta aplicació vol fer fotos i gravar vídeos sempre, fins i tot quan no l\'estiguis utilitzant. "<annotation id="link">"Pots permetre-ho a la configuració"</annotation>"."</string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Per permetre que l\'aplicació accedeixi sempre a les dades del sensor corporal, fins i tot quan no la 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="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlats"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlats"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> té accés a la ubicació"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"La teva organització permet a <xliff:g id="APP_NAME">%1$s</xliff:g> accedir a la teva ubicació"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Altres permisos"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Permís utilitzat pel sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Permisos utilitzats només per les aplicacions del sistema."</string>
@@ -520,7 +572,7 @@
<string name="blocked_microphone_title" msgid="1631517143648232585">"El micròfon del dispositiu està bloquejat"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"La ubicació del dispositiu està desactivada"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Per a aplicacions i serveis"</string>
- <string name="blocked_mic_summary" msgid="8960466941528458347">"És possible que les dades del micròfon es continuïn compartint quan truquis a un número d\'emergència."</string>
+ <string name="blocked_mic_summary" msgid="8960466941528458347">"És possible que les dades del micròfon es comparteixin si truques a un número d\'emergència."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Canvia"</string>
<string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Seguretat i privadesa"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Analitza el dispositiu"</string>
@@ -582,7 +634,7 @@
<string name="camera_toggle_title" msgid="1251201397431837666">"Accés a la càmera"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Accés al micròfon"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Per a aplicacions i serveis"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"Per a aplicacions i serveis. Si aquesta opció de configuració està desactivada, és possible que les dades del micròfon es continuïn compartint quan truquis a un número d\'emergència."</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"Per a aplicacions i serveis. És possible que les dades del micròfon es comparteixin si truques a un número d\'emergència encara que aquesta opció estigui desactivada."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Mostra les aplicacions i els serveis que tinguin accés a la ubicació"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Mostra l\'accés al porta-retalls"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Mostra un missatge quan les aplicacions accedeixen al text, a les imatges o a qualsevol altre contingut que hagis copiat"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Aquesta aplicació ha indicat que és possible que comparteixi dades d\'ubicació amb tercers"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Compartició de dades i ubicació"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"D\'on prové la informació de la compartició de dades"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"El desenvolupador ha proporcionat informació al fabricant del dispositiu sobre com comparteix dades aquesta app. És possible que el desenvolupador actualitzi aquesta informació al llarg del temps."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"El desenvolupador ha proporcionat informació a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre com comparteix dades aquesta aplicació. És possible que el desenvolupador actualitzi aquesta informació al llarg del temps."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"L\'aplicació pot compartir dades d\'ubicació per a:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"La compartició de dades varia"</string>
@@ -608,11 +661,9 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Seguretat de les dades"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Pot ser que les dades d\'ubicació es comparteixin"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Aquesta aplicació ha indicat que és possible que comparteixi les teves dades d\'ubicació amb tercers"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"No es pot obrir aquest enllaç"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Canvis en la compartició de dades per a la ubicació"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Revisa les aplicacions que han canviat la manera en què poden compartir les teves dades d\'ubicació"</string>
- <string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Aquestes aplicacions han canviat la manera en què poden compartir les teves dades d\'ubicació. Pot ser que no les hagin compartit abans o que ara les comparteixin amb finalitats publicitàries o de màrqueting."</string>
+ <string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Aquestes aplicacions han canviat la manera en què poden compartir les teves dades d\'ubicació. Pot ser que no les hagin compartit abans o que ara les comparteixin amb finalitats de màrqueting o publicitat."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Els desenvolupadors d\'aquestes aplicacions han proporcionat informació sobre les seves pràctiques de compartició de dades a una botiga d\'aplicacions. És possible que actualitzin la informació al llarg del temps.\n\nLes pràctiques de compartició de dades poden variar segons la versió de l\'aplicació, l\'ús, la regió i l\'edat."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Informació sobre la compartició de dades"</string>
<string name="shares_location_with_third_parties" msgid="2278051743742057767">"Les teves dades d\'ubicació ara es comparteixen amb tercers"</string>
diff --git a/PermissionController/res/values-cs-v33/strings.xml b/PermissionController/res/values-cs-v33/strings.xml
index e4dc33497..2e30db000 100644
--- a/PermissionController/res/values-cs-v33/strings.xml
+++ b/PermissionController/res/values-cs-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Další upozornění"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Zavřená upozornění"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Rozbalením zobrazíte jedno další upozornění}few{Rozbalením zobrazíte # další upozornění}many{Rozbalením zobrazíte # dalšího upozornění}other{Rozbalením zobrazíte # dalších upozornění}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Upozornění. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Akce dokončena"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Zkontrolujte nastavení, která mohou zvýšit ochranu vašeho zařízení"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Rychlé nastavení ochrany soukromí a zabezpečení"</string>
diff --git a/PermissionController/res/values-cs-v34/strings.xml b/PermissionController/res/values-cs-v34/strings.xml
index 828529402..b7e982b21 100644
--- a/PermissionController/res/values-cs-v34/strings.xml
+++ b/PermissionController/res/values-cs-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Zabezpečení a ochrana soukromí"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Ovládací prvky"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Spravovat přístup aplikací ke zdravotním údajům"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Správa přístupu aplikací ke zdravotním údajům"</string>
<string name="location_settings" msgid="8863940440881290182">"Přístup k poloze"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Aplikace a služby. Pokud je toto nastavení vypnuté a zavoláte na číslo tísňového volání, mohou být nadále sdílena data z mikrofonu"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Aplikace a služby. Pokud je toto nastavení vypnuté a zavoláte na číslo tísňového volání, data z mikrofonu bude možné nadále sdílet"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Aplikace a služby"</string>
</resources>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 22c104568..152fb24f9 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Používat přesnou polohu"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Když je přesná poloha vypnutá, aplikace mají přístup k vaší přibližné poloze"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Oprávnění: <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Aplikace má přístup k: <xliff:g id="PERM">%1$s</xliff:g>"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Přístup této aplikace k oprávnění: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<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>
@@ -399,7 +399,7 @@
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Tato služba sdílí vaše fotky, média a oznámení z telefonu s ostatními zařízeními."</string>
<string name="role_notes_label" msgid="7451627001058089536">"Výchozí aplikace pro poznámky"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Aplikace pro poznámky"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"Aplikace, které umožňují dělat si na zařízení poznámky"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"Aplikace, které umožňují dělat si na zařízení poznámky."</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"poznámky"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Aktuálně výchozí"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Příště se neptat"</string>
@@ -431,7 +431,7 @@
<string name="default_app_no_apps" msgid="115720991680586885">"Žádné aplikace"</string>
<string name="car_default_app_selected" msgid="5416420830430644174">"Vybráno"</string>
<string name="car_default_app_selected_with_info" msgid="1932204186080593500">"Vybráno – <xliff:g id="ADDITIONAL_INFO">%1$s</xliff:g>"</string>
- <string name="special_app_access_search_keyword" msgid="8032347212290774210">"přístup ke speciálním aplikacím"</string>
+ <string name="special_app_access_search_keyword" msgid="8032347212290774210">"zvláštní přístup aplikací"</string>
<string name="special_app_access" msgid="5019319067120213797">"Přístupy pro aplikace"</string>
<string name="no_special_app_access" msgid="6950277571805106247">"Žádný přístup ke spec. aplik."</string>
<string name="special_app_access_no_apps" msgid="4102911722787886970">"Žádné aplikace"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Zobrazit detekci spuštění asistenta"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Zobrazovat na stavovém řádku ikonu, když bude pomocí mikrofonu aktivován hlasový asistent"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k fotkám a mediálnímu obsahu v zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup ke kontaktům?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k poloze tohoto zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikace bude mít přístup k poloze, pouze když ji budete používat"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k poloze tohoto zařízení?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Aplikace může požadovat přístup k poloze vždy, i když ji nebudete používat. "<annotation id="link">"Povolit ho můžete v nastavení"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Změnit přístup k poloze pro aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplikace požaduje přístup k poloze vždy, i když ji nebudete používat. "<annotation id="link">"Povolit ho můžete v nastavení"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; najít zařízení v okolí, připojit se k nim a zjistit jejich relativní polohu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; najít zařízení v okolí, připojit se k nim a zjistit jejich relativní polohu? "<annotation id="link">"Povolit to můžete v nastavení."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Změnit přístup aplikace <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> k poloze z přibližné na přesnou?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k přibližné poloze tohoto zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Přesná"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Přibližná"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup ke kalendáři?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; odesílat a zobrazovat SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k fotkám, mediálnímu obsahu a souborům v zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k &lt;b&gt;fotkám, videím, hudbě a zvuku&lt;/b&gt; v zařízení?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k &lt;b&gt;fotkám, videím, hudbě, zvuku a dalším souborům&lt;/b&gt; v zařízení?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k hudbě a zvuku v zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k fotkám a videím v zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k dalším fotkám a videím v zařízení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nahrávat zvuk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikace bude moci zaznamenávat zvuk, pouze když ji budete používat"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nahrávat zvuk?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Tato aplikace může chtít zaznamenávat zvuk kdykoli, dokonce i když ji nepoužíváte. "<annotation id="link">"Povolit v nastavení"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Změnit přístup k mikrofonu pro aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Tato aplikace chce zaznamenávat zvuk kdykoli, dokonce i když ji nepoužíváte. "<annotation id="link">"Povolit v nastavení"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; přístup k vaší fyzické aktivitě?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotit a nahrávat videa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikace bude moci pořizovat snímky a nahrávat videa, pouze když ji budete používat"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotit a nahrávat videa?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Tato aplikace může chtít pořizovat snímky a nahrávat videa kdykoli, dokonce i když ji nepoužíváte. "<annotation id="link">"Povolit v nastavení"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Změnit přístup k fotoaparátu pro aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Tato aplikace chce pořizovat snímky a nahrávat videa kdykoli, dokonce i když ji nepoužíváte. "<annotation id="link">"Povolit v nastavení"</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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 senzorů vašich životních funkcí?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Spravovaná oprávnění"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Spravovaná oprávnění"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> má přístup k poloze"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Vaše organizace umožňuje aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> přístup k vaší poloze"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Jiná oprávnění"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Oprávnění používaná systémem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Oprávnění, která jsou používaná pouze systémovými aplikacemi."</string>
@@ -518,7 +570,7 @@
<string name="exempt_info_label" msgid="6286190981253476699">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> je chráněna Androidem. Protože se vaše data zpracovávají na tomto zařízení, oprávnění používaná touto aplikací se nezobrazují na panelu ochrany soukromí."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"Fotoaparát zařízení je blokován"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"Mikrofon zařízení je blokován"</string>
- <string name="blocked_location_title" msgid="2005608279812892383">"Ukládání polohy zařízení je vypnuté"</string>
+ <string name="blocked_location_title" msgid="2005608279812892383">"Zjišťování polohy zařízení je vypnuté"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Pro aplikace a služby"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Když zavoláte na číslo tísňového volání, mohou být nadále sdílena data z mikrofonu."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Změnit"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Tato aplikace uvedla, že může sdílet údaje o poloze se třetími stranami"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Sdílení dat a poloha"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Odkud informace o sdílení dat pocházejí"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Vývojář poskytl výrobci tohoto zařízení informace o tom, jak tato aplikace sdílí data. Tyto informace může vývojář průběžně aktualizovat."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Vývojář poskytl obchodu "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" informace o tom, jak tato aplikace sdílí data. Tyto informace může vývojář průběžně aktualizovat."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Možné účely sdílení údajů o poloze touto aplikací:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Sdílení dat se liší"</string>
@@ -608,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Zabezpečení údajů"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Mohou být sdíleny údaje o poloze"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Tato aplikace uvedla, že může sdílet údaje o vaší poloze se třetími stranami"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Odkaz nelze otevřít"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Aktualizace sdílení údajů o poloze"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"Zkontrolujte aplikace, které změnily způsob, jakým mohou sdílet údaje o vaší poloze"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"Kontrola aplikací, které změnily způsob, jakým mohou sdílet údaje o vaší poloze"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Tyto aplikace změnily způsob, jakým mohou sdílet údaje o vaší poloze. Buď je dříve nesdílely, nebo je nyní mohou sdílet pro reklamní nebo marketingové účely."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Vývojáři těchto aplikací poskytli obchodu s aplikacemi informace o svých postupech sdílení dat. Tyto informace mohou průběžně aktualizovat.\n\nPostupy sdílení dat se mohou lišit v závislosti na verzi aplikace, použití, oblasti a věku uživatele."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Informace o sdílení dat"</string>
diff --git a/PermissionController/res/values-da-v33/strings.xml b/PermissionController/res/values-da-v33/strings.xml
index 91351105a..3e532459f 100644
--- a/PermissionController/res/values-da-v33/strings.xml
+++ b/PermissionController/res/values-da-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Flere underretninger"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Lukkede underretninger"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Udvid for at se én yderligere advarsel}one{Udvid for at se # yderligere advarsel}other{Udvid for at se # yderligere advarsler}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Underretning. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Handlingen er udført"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Tjek indstillinger, der kan øge sikkerheden på din enhed"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Kvikmenu for sikkerheds- og privatlivsindstillinger"</string>
diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml
index b34c8adc1..3808a21f2 100644
--- a/PermissionController/res/values-da/strings.xml
+++ b/PermissionController/res/values-da/strings.xml
@@ -68,7 +68,7 @@
<string name="auto_permission_manager_summary" msgid="9157438376234301354">"Administrer adgang til data for kalender, opkaldshistorik m.m."</string>
<string name="granted_permission_decision" msgid="7824827491551861365">"Du har givet <xliff:g id="APP_NAME">%1$s</xliff:g> adgang til <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="denied_permission_decision" msgid="5308961501779563781">"Du har nægtet <xliff:g id="APP_NAME">%1$s</xliff:g> adgang til <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
- <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{I dag}=1{For 1 dag siden}one{for # dag siden}other{for # dage siden}}"</string>
+ <string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{I dag}=1{1 dag siden}one{# dag siden}other{# dage siden}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Deaktiver appen"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Hvis du deaktiverer denne app, kan det medføre, at Android-apps og andre apps ikke fungerer korrekt. Vær opmærksom på, at du ikke kan slette denne app, da den er forudinstalleret på din enhed. Hvis du slår appen fra, deaktiveres og skjules den på din enhed."</string>
<string name="app_permission_manager" msgid="3903811137630909550">"Tilladelses­administrator"</string>
@@ -295,13 +295,13 @@
<string name="accessibility_show_all_apps_button_label" msgid="960067249326392280">"Se apps med fuld adgang"</string>
<string name="accessibility_remove_access_success_label" msgid="4380995302917014670">"Adgangen er blevet fjernet"</string>
<string name="safety_center_notification_app_label" msgid="2457720616141926534">"Android-system"</string>
- <string name="auto_revoke_after_notification_title" msgid="5417761027669887431">"Apptilladelserne blev fjernet for at beskytte dine personlige oplysninger"</string>
+ <string name="auto_revoke_after_notification_title" msgid="5417761027669887431">"Apptilladelserne blev fjernet for at beskytte dit privatliv"</string>
<string name="auto_revoke_after_notification_content_one" msgid="6804038707453662753">"<xliff:g id="APP_NAME">%s</xliff:g> er ikke blevet brugt i et par måneder. Tryk for at gennemgå."</string>
<string name="auto_revoke_after_notification_content_two" msgid="9108709764831425172">"<xliff:g id="APP_NAME">%s</xliff:g> og 1 anden app er ikke blevet brugt i et par måneder. Tryk for at gennemgå."</string>
<string name="auto_revoke_after_notification_content_many" msgid="4774106206289751220">"<xliff:g id="APP_NAME">%1$s</xliff:g> og <xliff:g id="NUMBER_OF_APPS">%2$s</xliff:g> andre apps er ikke blevet brugt i et par måneder. Tryk for at gennemgå."</string>
<string name="auto_revoke_before_notification_title_one" msgid="6758024954464359876">"1 app bruges ikke"</string>
<string name="auto_revoke_before_notification_title_many" msgid="4415543943846385685">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> apps bruges ikke"</string>
- <string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"Tilladelserne fjernes for at beskytte dine personlige oplysninger. Tryk for at gennemgå."</string>
+ <string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"Tilladelserne fjernes for at beskytte dit privatliv. Tryk for at gennemgå."</string>
<string name="unused_apps_title" msgid="8589298917717872239">"Apps, du ikke bruger"</string>
<string name="unused_apps_subtitle_after" msgid="2034267519506357898">"Tilladelserne blev fjernet fra"</string>
<string name="unused_apps_subtitle_before" msgid="5233302577076132427">"Tilladelserne fjernes fra"</string>
@@ -373,7 +373,7 @@
<string name="role_emergency_request_title" msgid="8469579020654348567">"Vil du angive <xliff:g id="APP_NAME">%1$s</xliff:g> som din standardnødapp?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"Der kræves ingen tilladelser"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"i nødsituationer"</string>
- <string name="role_home_label" msgid="3871847846649769412">"Standardstartapp"</string>
+ <string name="role_home_label" msgid="3871847846649769412">"Standard­startapp"</string>
<string name="role_home_short_label" msgid="8544733747952272337">"Startapp"</string>
<string name="role_home_description" msgid="7997371519626556675">"Apps (ofte kaldet launchers), som erstatter startskærmene på din Android-enhed og giver dig adgang til indhold og funktioner på din enhed"</string>
<string name="role_home_request_title" msgid="738136983453341081">"Vil du angive <xliff:g id="APP_NAME">%1$s</xliff:g> som din standardstartapp?"</string>
@@ -443,7 +443,7 @@
<string name="incident_report_notification_text" msgid="3376480583513587923">"<xliff:g id="APP_NAME">%1$s</xliff:g> vil gerne uploade fejretningsoplysninger."</string>
<string name="incident_report_dialog_title" msgid="669104389325204095">"Vil du dele fejlretningsdata?"</string>
<string name="incident_report_dialog_intro" msgid="5897733669850951832">"Systemet har registreret et problem."</string>
- <string name="incident_report_dialog_text" msgid="5675553296891757523">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> anmoder om at uploade en fejlrapport fra denne enhed, som stammer fra <xliff:g id="DATE">%2$s</xliff:g> kl. <xliff:g id="TIME">%3$s</xliff:g>. Fejlrapporter indeholder personlige oplysninger om din enhed eller registreres af apps, f.eks. brugernavne, steddata, enheds-id\'er og netværksoplysninger. Oplysningerne i fejlrapporterne må kun deles med personer og apps, du har tillid til. Vil du give <xliff:g id="APP_NAME_1">%4$s</xliff:g> tilladelse til at uploade en fejlrapport?"</string>
+ <string name="incident_report_dialog_text" msgid="5675553296891757523">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> anmoder om at uploade en fejlrapport fra denne enhed, som stammer fra <xliff:g id="DATE">%2$s</xliff:g> kl. <xliff:g id="TIME">%3$s</xliff:g>. Fejlrapporter indeholder personlige oplysninger om din enhed eller registreres af apps, f.eks. brugernavne, lokationsdata, enheds-id\'er og netværksoplysninger. Oplysningerne i fejlrapporterne må kun deles med personer og apps, du har tillid til. Vil du give <xliff:g id="APP_NAME_1">%4$s</xliff:g> tilladelse til at uploade en fejlrapport?"</string>
<string name="incident_report_error_dialog_text" msgid="4189647113387092272">"Der opstod en fejl i behandlingen af fejlrapporten for <xliff:g id="APP_NAME">%1$s</xliff:g>. Det er derfor ikke muligt at dele detaljerede fejlretningsdata. Vi beklager ulejligheden."</string>
<string name="incident_report_dialog_allow_label" msgid="2970242967721155239">"Tillad"</string>
<string name="incident_report_dialog_deny_label" msgid="3535314290677579383">"Afvis"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Vis aktiveringsregistrering for assistenten"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Vis ikon på statusbjælken, når mikrofonen bruges til at aktivere taleassistenten"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til billeder og medier på din enhed?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til dine kontakter?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til enhedens lokation?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Appen har kun adgang til lokationen, når du bruger appen"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til enhedens lokation?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Denne app vil muligvis gerne have adgang til din lokation hele tiden, også når du ikke bruger appen. "<annotation id="link">"Giv tilladelse under Indstillinger."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vil du skifte lokationsadgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Appen vil gerne have adgang til din lokation hele tiden, også når du ikke bruger appen. "<annotation id="link">"Giv appen tilladelse i Indstillinger."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Skal &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kunne finde, oprette forbindelse til og fastslå den relative placering af enheder i nærheden?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Skal &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kunne finde, oprette forbindelse til og fastslå den relative placering af enheder i nærheden? "<annotation id="link">"Tillad i Indstillinger."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Vil du skifte lokationsadgang for <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> fra omtrentlig til nøjagtig?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til enhedens omtrentlige lokation?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Præcis"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Omtrentlig"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til din kalender?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at sende og se sms-beskeder?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til billeder, medier og filer på din enhed?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til &lt;b&gt;billeder, videoer, musik og lyd&lt;/b&gt; på denne enhed?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til &lt;b&gt;billeder, videoer, musik, lyd og andre filer&lt;/b&gt; på denne enhed?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til musik og lyd på denne enhed?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; adgang til billeder og videoer på denne enhed?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at tilgå flere billeder og videoer på denne enhed?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at optage lyd?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Appen kan kun optage lyd, mens du bruger appen"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at optage lyd?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Denne app vil gerne optage lyd hele tiden, også når du ikke bruger appen. "<annotation id="link">"Tillad dette i indstillingerne"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vil du skifte mikrofonadgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Denne app vil gerne optage lyd hele tiden, også når du ikke bruger appen. "<annotation id="link">"Tillad dette i indstillingerne"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vil du tillade, at &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; får adgang til din fysiske aktivitet?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at tage billeder og optage video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Appen kan kun tage billeder og optage video, mens du bruger appen"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at tage billeder og optage video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Denne app vil gerne tage billeder og optage video hele tiden, også når du ikke bruger appen. "<annotation id="link">"Tillad dette i indstillingerne"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vil du skifte kameraadgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Denne app vil gerne tage billeder og optage video hele tiden, også når du ikke bruger appen. "<annotation id="link">"Tillad dette i indstillingerne"</annotation>"."</string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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 vitale værdier?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Du kan give denne app adgang til kropssensordata 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="auto_granted_permissions" msgid="6009452264824455892">"Administrerede tilladelser"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Administrerede tilladelser"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> har lokationsadgang"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Din organisation har givet <xliff:g id="APP_NAME">%1$s</xliff:g> tilladelse til at tilgå din lokation"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Andre tilladelser"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Tilladelse, der anvendes af systemet"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Tilladelser, der kun anvendes af systemapps"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Denne app har angivet, at den muligvis deler lokationsdata med tredjeparter"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datadeling og lokation"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Hvor oplysninger om datadeling stammer fra"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Udvikleren har stillet oplysninger om, hvordan denne app deler data, til rådighed for producenten af denne enhed. Udvikleren opdaterer muligvis disse oplysninger senere."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Udvikleren gav oplysninger til "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" om, hvordan denne app deler data. Udvikleren opdaterer muligvis disse oplysninger senere."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Denne app deler muligvis lokationsdata for:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datadeling varierer"</string>
@@ -603,13 +656,11 @@
<string name="permission_rationale_purpose_developer_communications" msgid="6453047018892062374">"Kommunikation fra udvikleren"</string>
<string name="permission_rationale_purpose_advertising" msgid="7156966429245180236">"Annoncering eller marketing"</string>
<string name="permission_rationale_purpose_fraud_prevention_security" msgid="4262104770357031902">"Sikkerhed, overholdelse og forebyggelse af svindel"</string>
- <string name="permission_rationale_purpose_personalization" msgid="1589973273682238708">"Tilpasning"</string>
+ <string name="permission_rationale_purpose_personalization" msgid="1589973273682238708">"Personlig tilpasning"</string>
<string name="permission_rationale_purpose_account_management" msgid="2985772421946688879">"Kontoadministration"</string>
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datasikkerhed"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Lokationsdata deles muligvis"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Denne app har angivet, at den muligvis deler dine lokationsdata med tredjeparter"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Dette link kan ikke åbnes"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Opdateringer om deling af lokationsdata"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Gennemse apps, der har ændret måden, hvorpå de kan dele dine lokationsdata"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Disse apps har ændret den måde, hvorpå de kan dele dine lokationsdata. De har muligvis ikke delt dataene før eller kan nu anvende dem til annoncering eller marketing."</string>
diff --git a/PermissionController/res/values-de-v33/strings.xml b/PermissionController/res/values-de-v33/strings.xml
index 023368660..d82bd4619 100644
--- a/PermissionController/res/values-de-v33/strings.xml
+++ b/PermissionController/res/values-de-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Weitere Benachrichtigungen"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Ausgeblendete Benachrichtigungen"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Maximieren und eine weitere Warnung anzeigen}other{Maximieren und # weitere Warnungen anzeigen}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Warnung. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Aktion abgeschlossen"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Einstellungen aufrufen, mit denen sich der Schutz meines Geräts verbessern lässt"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Schnelleinstellungen für Sicherheit und Datenschutz"</string>
diff --git a/PermissionController/res/values-de-v34/strings.xml b/PermissionController/res/values-de-v34/strings.xml
index 4a97b4d4b..8b6f95055 100644
--- a/PermissionController/res/values-de-v34/strings.xml
+++ b/PermissionController/res/values-de-v34/strings.xml
@@ -22,7 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"App-Zugriff auf Gesundheitsdaten verwalten"</string>
<string name="location_settings" msgid="8863940440881290182">"Standortzugriff"</string>
- <!-- no translation found for mic_toggle_description (1504101620086616040) -->
- <skip />
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Für Apps und Dienste. Wenn du eine Notrufnummer wählst, können Mikrofondaten trotz Deaktivierung dieser Berechtigung weitergegeben werden."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Für Apps und Dienste"</string>
</resources>
diff --git a/PermissionController/res/values-de/strings.xml b/PermissionController/res/values-de/strings.xml
index e3855033e..942f8f7e2 100644
--- a/PermissionController/res/values-de/strings.xml
+++ b/PermissionController/res/values-de/strings.xml
@@ -58,7 +58,7 @@
<string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"Verwaltung aller Dateien zulassen"</string>
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"Zugriff auf Mediendateien zulassen"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Apps"</string>
- <string name="app_permissions" msgid="3369917736607944781">"App-Berechtigungen"</string>
+ <string name="app_permissions" msgid="3369917736607944781">"App-Berech­tigungen"</string>
<string name="unused_apps" msgid="2058057455175955094">"Nicht verwendete Apps"</string>
<string name="no_unused_apps" msgid="12809387670415295">"Keine nicht verwendeten Apps"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Keine nicht verwendeten Apps"</string>
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Heute}=1{Vor 1 Tag}other{Vor # Tagen}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"App deaktivieren"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Bei Deaktivierung dieser App funktionieren Android und andere Apps möglicherweise nicht mehr ordnungsgemäß. Beachte hierbei, dass du diese App nicht löschen kannst, weil sie auf deinem Gerät vorinstalliert war. Durch die Deaktivierung schaltest du diese App ab und blendest sie auf deinem Gerät aus."</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"Berechtigungs­manager"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"Berechti­gungsmanager"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Nicht mehr fragen"</string>
<string name="no_permissions" msgid="3881676756371148563">"Keine Berechtigungen"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Zusätzliche Berechtigungen"</string>
@@ -426,7 +426,7 @@
<string name="default_apps_more" msgid="4078194675848858093">"Weitere Standard-Apps"</string>
<string name="default_apps_manage_domain_urls" msgid="6775566451561036069">"Links öffnen"</string>
<string name="default_apps_for_work" msgid="4970308943596201811">"Standard-Apps für Arbeit"</string>
- <string name="default_app_none" msgid="9084592086808194457">"Keine App"</string>
+ <string name="default_app_none" msgid="9084592086808194457">"Keine"</string>
<string name="default_app_system_default" msgid="6218386768175513760">"(System-Standardeinstellung)"</string>
<string name="default_app_no_apps" msgid="115720991680586885">"Keine Apps"</string>
<string name="car_default_app_selected" msgid="5416420830430644174">"Ausgewählt"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Auslösererkennung für Assistenten anzeigen"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Symbol in der Statusleiste anzeigen, wenn das Mikrofon verwendet wird, um den Sprachassistenten zu aktivieren"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Fotos und Medien auf deinem Gerät zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ erlauben, auf deine Kontakte zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, den Gerätestandort abzurufen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Die App hat nur Zugriff auf den Gerätestandort, solange du sie verwendest"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, den Gerätestandort abzurufen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Diese App möchte eventuell Zugriff auf deinen Standort haben, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Standortzugriff für &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ändern?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Diese App möchte jederzeit Zugriff auf deinen Standort haben, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Zulassen, dass &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; Geräte in der Nähe finden, sich mit ihnen verbinden und ihre relative Position bestimmen kann?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Zulassen, dass &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; Geräte in der Nähe finden, sich mit ihnen verbinden und ihre relative Position bestimmen kann? "<annotation id="link">"In den Einstellungen zulassen."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Soll der Standortzugriff von <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> von „Ungefähr“ zu „Genau“ geändert werden?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, den ungefähren Gerätestandort abzurufen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Genau"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Ungefähr"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf deinen Kalender zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, SMS zu senden und aufzurufen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Fotos, Medien und Dateien auf deinem Gerät zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf &lt;b&gt;Foto-, Video-, Musik- und Audiodateien&lt;/b&gt; auf diesem Gerät zuzugreifen?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf &lt;b&gt;Foto-, Video-, Musik-, Audio- und andere Dateien&lt;/b&gt; auf diesem Gerät zuzugreifen?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Musik- und Audiodateien auf diesem Gerät zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf Fotos und Videos auf diesem Gerät zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Darf &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; auf weitere Fotos und Videos auf diesem Gerät zugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Audioaufnahmen zu machen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Diese App kann nur Audioaufnahmen machen, solange du sie verwendest"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Audioaufnahmen zu machen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Diese App möchte ggf. jederzeit Audioaufnahmen machen können, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Mikrofonzugriff für &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ändern?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Diese App möchte jederzeit Audioaufnahmen machen können, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, auf deine körperliche Aktivität zuzugreifen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Bilder und Videos aufzunehmen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Diese App kann nur Bilder und Videos aufnehmen, solange du sie verwendest"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Bilder und Videos aufzunehmen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Diese App möchte ggf. jederzeit Bilder und Videos aufnehmen können, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Kamerazugriff für &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ändern?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Diese App möchte jederzeit Bilder und Videos aufnehmen können, auch wenn du sie nicht verwendest. "<annotation id="link">"Du kannst das in den Einstellungen zulassen."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Damit diese App dauerhaft auf Daten des Körpersensors zugreifen kann, auch dann, wenn sie nicht verwendet wird, "<annotation id="link">"rufe die Einstellungen auf"</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 Verwendung 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="auto_granted_permissions" msgid="6009452264824455892">"Erteilte Berechtigungen"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Erteilte Berechtigungen"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> hat Standortzugriff"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Deine Organisation erlaubt <xliff:g id="APP_NAME">%1$s</xliff:g> den Zugriff auf deinen Standort"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Weitere Berechtigungen"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Berechtigungen, die vom System verwendet werden"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Berechtigungen, die nur von Systemanwendungen verwendet werden."</string>
@@ -522,7 +574,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Für Apps und Dienste"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Die Mikrofondaten können immer noch geteilt werden, wenn du den Notruf wählst."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Ändern"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Sicherheit und Datenschutz"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Sicherheit &amp; Datenschutz"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Gerät prüfen"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Schließen"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Diese Warnung schließen?"</string>
@@ -533,7 +585,7 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"Sicherheits- und Datenschutzstatus. <xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>. <xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"Sicherheitseinstellungen"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Berechtigungen"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Sicherheit und Datenschutz"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Sicherheit &amp; Datenschutz"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Status prüfen"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Datenschutzeinstellungen"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Weitere Einstellungen"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"In dieser App wurde angegeben, dass sie eventuell Standortdaten an Dritte weitergibt"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datenweitergabe und Standort"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Ursprung der Informationen zur Datenweitergabe"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Die Informationen darüber, wie diese App Daten weitergibt, hat der Hersteller des Geräts vom Entwickler erhalten. Der Entwickler kann die Art und Weise der Datenweitergabe jederzeit ändern."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Der Entwickler hat "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" Informationen darüber zur Verfügung gestellt, wie diese App Daten weitergibt. Der Entwickler kann diese Informationen jederzeit ändern."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Diese App kann Standortdaten weitergeben für:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datenweitergabe variiert"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datensicherheit"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Die App kann Standortdaten weitergeben"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Für diese App wurde angegeben, dass deine Standortdaten an Dritte weitergegeben werden können"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Link konnte nicht geöffnet werden"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Änderungen bei der Weitergabe von Standortdaten"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Apps ansehen, bei denen sich die Art der Weitergabe deiner Standortdaten geändert hat"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Bei diesen Apps hat sich die Art der Weitergabe deiner Standortdaten geändert. Möglicherweise wurden sie zuvor nicht weitergegeben oder sie werden jetzt zu Werbe- oder Marketingzwecken weitergegeben."</string>
diff --git a/PermissionController/res/values-el-v33/strings.xml b/PermissionController/res/values-el-v33/strings.xml
index 97291b070..4cefe7f04 100644
--- a/PermissionController/res/values-el-v33/strings.xml
+++ b/PermissionController/res/values-el-v33/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="role_dialer_request_description" msgid="6188305064871543419">"Αυτή η εφαρμογή θα μπορεί να σας στέλνει ειδοποιήσεις και θα έχει πρόσβαση στην κάμερα, τις επαφές, το μικρόφωνο, το τηλέφωνο και τα SMS."</string>
<string name="role_sms_request_description" msgid="1506966389698625395">"Αυτή η εφαρμογή θα μπορεί να σας στέλνει ειδοποιήσεις και θα έχει πρόσβαση στην κάμερα, τις επαφές, τα αρχεία, το μικρόφωνο, το τηλέφωνο και τα SMS."</string>
- <string name="permission_description_summary_storage" msgid="1917071243213043858">"Οι εφαρμογές με αυτήν την άδεια μπορούν να έχουν πρόσβαση σε όλα τα αρχεία αυτής της συσκευής"</string>
+ <string name="permission_description_summary_storage" msgid="1917071243213043858">"Οι εφαρμογές με αυτή την άδεια μπορούν να έχουν πρόσβαση σε όλα τα αρχεία αυτής της συσκευής"</string>
<string name="work_policy_title" msgid="832967780713677409">"Οι πληροφορίες πολιτικής εργασίας σας"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"Η διαχείριση των ρυθμίσεων πραγματοποιείται από τον διαχειριστή IT"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Ανάπτυξη και εμφάνιση λίστας"</string>
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Περισσότερες ειδοποιήσεις"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Ειδοποιήσεις που παραβλέφθηκαν"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Αναπτύξτε και δείτε μία ακόμη ειδοποίηση}other{Αναπτύξτε και δείτε # ακόμη ειδοποιήσεις}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Ειδοποίηση. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Η ενέργεια ολοκληρώθηκε"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Ελέγξτε ρυθμίσεις που μπορούν να προσθέσουν προστασία στη συσκευή σας"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Γρήγορες ρυθμίσεις ασφάλειας και απορρήτου"</string>
diff --git a/PermissionController/res/values-el/strings.xml b/PermissionController/res/values-el/strings.xml
index 5d0031ed9..5981b3ee0 100644
--- a/PermissionController/res/values-el/strings.xml
+++ b/PermissionController/res/values-el/strings.xml
@@ -32,7 +32,7 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"Διατήρηση της επιλογής \"Όταν χρησιμοποιείται η εφαρμογή\""</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"Διατήρηση μόνο αυτήν τη φορά"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Περισσότερα"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Να επιτρέπονται όλα"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Να επιτρέπεται"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Να επιτρέπονται πάντα όλα"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Επιλογή φωτογραφιών και βίντεο"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Επιλέξτε περισσότερα"</string>
@@ -70,7 +70,7 @@
<string name="denied_permission_decision" msgid="5308961501779563781">"Δεν επιτρέψατε στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> να έχει πρόσβαση στην άδεια <xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Σήμερα}=1{Πριν από 1 ημέρα}other{Πριν από # ημέρες}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Απενεργοποίηση εφαρμογής"</string>
- <string name="app_disable_dlg_text" msgid="3126943217146120240">"Εάν απενεργοποιήσετε αυτήν την εφαρμογή, η λειτουργία του Android και άλλων εφαρμογών ενδέχεται να μην είναι η αναμενόμενη. Λάβετε υπόψη ότι δεν είναι δυνατή η διαγραφή αυτής της εφαρμογής καθώς ήταν προεγκατεστημένη στη συσκευή σας. Με την απενεργοποίηση, απενεργοποιείτε αυτήν την εφαρμογή και την αποκρύπτετε στη συσκευή σας."</string>
+ <string name="app_disable_dlg_text" msgid="3126943217146120240">"Εάν απενεργοποιήσετε αυτή την εφαρμογή, η λειτουργία του Android και άλλων εφαρμογών ενδέχεται να μην είναι η αναμενόμενη. Λάβετε υπόψη ότι δεν είναι δυνατή η διαγραφή αυτής της εφαρμογής καθώς ήταν προεγκατεστημένη στη συσκευή σας. Με την απενεργοποίηση, απενεργοποιείτε αυτή την εφαρμογή και την αποκρύπτετε στη συσκευή σας."</string>
<string name="app_permission_manager" msgid="3903811137630909550">"Διαχείριση αδειών"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Να μην ερωτηθώ ξανά"</string>
<string name="no_permissions" msgid="3881676756371148563">"Δεν υπάρχουν άδειες"</string>
@@ -78,8 +78,8 @@
<string name="app_permissions_info_button_label" msgid="7633312050729974623">"Άνοιγμα πληροφοριών εφαρμογής"</string>
<string name="additional_permissions_more" msgid="5681220714755304407">"{count,plural, =1{# ακόμη}other{# ακόμη}}"</string>
<string name="old_sdk_deny_warning" msgid="2382236998845153919">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Η άρνηση παραχώρησης άδειας μπορεί να έχει ως αποτέλεσμα να διακοπεί η κανονική λειτουργία της."</string>
- <string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν επιτρέψετε αυτήν την άδεια, τότε θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
- <string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε αυτήν την άδεια, τότε δεν θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
+ <string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν επιτρέψετε αυτή την άδεια, τότε θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
+ <string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε αυτή την άδεια, τότε δεν θα επιτρέπεται η πρόσβαση σε όλο τον αποθηκευτικό χώρο (συμπεριλαμβανομένων φωτογραφιών, βίντεο, μουσικής, ήχου και άλλων αρχείων)."</string>
<string name="default_permission_description" msgid="4624464917726285203">"εκτέλεση άγνωστης ενέργειας"</string>
<string name="app_permissions_group_summary" msgid="8788419008958284002">"Επιτρέπονται <xliff:g id="COUNT_0">%1$d</xliff:g> από <xliff:g id="COUNT_1">%2$d</xliff:g> εφαρμογές"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"Επιτρέπονται <xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> εφαρμογές"</string>
@@ -91,10 +91,10 @@
<string name="no_apps" msgid="2412612731628386816">"Δεν υπάρχουν εφαρμογές"</string>
<string name="location_settings" msgid="3624412509133422562">"Ρυθμίσεις τοποθεσίας"</string>
<string name="location_warning" msgid="2381649060929040962">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> είναι ο πάροχος των υπηρεσιών τοποθεσίας για τη συγκεκριμένη συσκευή. Μπορείτε να τροποποιήσετε την πρόσβαση τοποθεσίας από τις ρυθμίσεις τοποθεσίας."</string>
- <string name="system_warning" msgid="1173400963234358816">"Εάν αρνηθείτε να παραχωρήσετε αυτήν την άδεια, ορισμένες βασικές λειτουργίες της συσκευής σας μπορεί να μην εκτελούνται πλέον με τον αναμενόμενο τρόπο."</string>
+ <string name="system_warning" msgid="1173400963234358816">"Εάν αρνηθείτε να παραχωρήσετε αυτή την άδεια, ορισμένες βασικές λειτουργίες της συσκευής σας μπορεί να μην εκτελούνται πλέον με τον αναμενόμενο τρόπο."</string>
<string name="deny_read_media_visual_warning" msgid="3982586279917232827">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε την πρόσβαση αυτής της εφαρμογής στις φωτογραφίες και τα βίντεο, δεν θα επιτρέπεται επίσης η πρόσβαση στη μουσική και άλλους ήχους."</string>
<string name="deny_read_media_aural_warning" msgid="8928699919508646732">"Αυτή η εφαρμογή σχεδιάστηκε για παλαιότερη έκδοση του Android. Εάν δεν επιτρέψετε την πρόσβαση αυτής της εφαρμογής στη μουσική και άλλους ήχους, δεν θα επιτρέπεται επίσης η πρόσβαση στις φωτογραφίες και τα βίντεο."</string>
- <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Εάν απορρίψετε αυτήν την άδεια, ορισμένες λειτουργίες της συσκευής σας τις οποίες διαχειρίζεται αυτή η εφαρμογή, ενδέχεται να μην λειτουργούν με τον αναμενόμενο τρόπο."</string>
+ <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"Εάν απορρίψετε αυτή την άδεια, ορισμένες λειτουργίες της συσκευής σας τις οποίες διαχειρίζεται αυτή η εφαρμογή, ενδέχεται να μην λειτουργούν με τον αναμενόμενο τρόπο."</string>
<string name="permission_summary_enforced_by_policy" msgid="4443598170942950519">"Επιβάλλεται βάσει πολιτικής"</string>
<string name="permission_summary_disabled_by_policy_background_only" msgid="221995005556362660">"Η πρόσβαση στο παρασκήνιο απενεργοποιήθηκε βάσει πολιτικής"</string>
<string name="permission_summary_enabled_by_policy_background_only" msgid="8287675974767104279">"Η πρόσβαση στο παρασκήνιο ενεργοποιήθηκε βάσει πολιτικής"</string>
@@ -196,16 +196,16 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Χρήση ακριβούς τοποθεσίας"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Όταν είναι απενεργοποιημένη η ακριβής τοποθεσία, οι εφαρμογές μπορούν να έχουν πρόσβαση στην κατά προσέγγιση τοποθεσία σας"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Άδεια - <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Πρόσβαση σε <xliff:g id="PERM">%1$s</xliff:g> για αυτήν την εφαρμογή"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Πρόσβαση σε <xliff:g id="PERM">%1$s</xliff:g> για αυτή την εφαρμογή"</string>
<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="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" 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>
<string name="auto_revoke_open_app_message" msgid="8075556291711205039">"Εάν θέλετε να επιτραπούν ξανά οι άδειες, ανοίξτε την εφαρμογή."</string>
@@ -225,22 +225,22 @@
<string name="last_opened_summary" msgid="5248984030024968808">"Τελευταίο άνοιγμα εφαρμογής <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"Τελευταίο άνοιγμα <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Εάν επιτρέψετε τη διαχείριση όλων των αρχείων, αυτή η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση, να τροποποιήσει και να διαγράψει τυχόν αρχεία στον κοινό αποθηκευτικό χώρο αυτής της συσκευής ή συνδεδεμένων συσκευών αποθηκευτικού χώρου. Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
- <string name="special_file_access_dialog" msgid="583804114020740610">"Να επιτρέπεται σε αυτήν την εφαρμογή η πρόσβαση, τροποποίηση και διαγραφή αρχείων στη συσκευή ή τυχόν συνδεδεμένες συσκευές αποθηκευτικού χώρου; Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Οι εφαρμογές με αυτήν την άδεια μπορούν να <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
- <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Οι εφαρμογές με αυτήν την άδεια έχουν πρόσβαση σε φυσικές δραστηριότητες, όπως το περπάτημα, η ποδηλασία, η οδήγηση, ο αριθμός βημάτων και άλλα"</string>
- <string name="permission_description_summary_calendar" msgid="103329982944411010">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στο ημερολόγιό σας"</string>
- <string name="permission_description_summary_call_log" msgid="7321437186317577624">"Οι εφαρμογές με αυτήν την άδεια, έχουν δυνατότητα ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων"</string>
- <string name="permission_description_summary_camera" msgid="108004375101882069">"Οι εφαρμογές με αυτήν την άδεια μπορούν να τραβούν φωτογραφίες και να εγγράφουν βίντεο"</string>
- <string name="permission_description_summary_contacts" msgid="2337798886460408996">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στις επαφές σας"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στην τοποθεσία αυτής της συσκευής"</string>
- <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Οι εφαρμογές με αυτήν την άδεια μπορούν να βρίσκουν, να συνδέονται και να προσδιορίζουν τη σχετική τοποθεσία κοντινών συσκευών"</string>
- <string name="permission_description_summary_microphone" msgid="630834800308329907">"Οι εφαρμογές με αυτήν την άδεια μπορούν να εγγράφουν ήχο"</string>
- <string name="permission_description_summary_phone" msgid="4515277217435233619">"Οι εφαρμογές με αυτήν την άδεια έχουν δυνατότητα πραγματοποίησης και διαχείρισης τηλεφωνικών κλήσεων"</string>
- <string name="permission_description_summary_sensors" msgid="1836045815643119949">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
- <string name="permission_description_summary_sms" msgid="725999468547768517">"Οι εφαρμογές με αυτήν την άδεια μπορούν να στέλνουν και να προβάλλουν μηνύματα SMS"</string>
- <string name="permission_description_summary_storage" msgid="6575759089065303346">"Οι εφαρμογές με αυτήν την άδεια έχουν πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string>
- <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στη μουσική και σε άλλα αρχεία ήχου αυτής της συσκευής"</string>
- <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Οι εφαρμογές με αυτήν την άδεια μπορούν να αποκτήσουν πρόσβαση στις φωτογραφίες και τα βίντεο αυτής της συσκευής"</string>
+ <string name="special_file_access_dialog" msgid="583804114020740610">"Να επιτρέπεται σε αυτή την εφαρμογή η πρόσβαση, τροποποίηση και διαγραφή αρχείων στη συσκευή ή τυχόν συνδεδεμένες συσκευές αποθηκευτικού χώρου; Η εφαρμογή θα μπορεί να αποκτήσει πρόσβαση σε αρχεία χωρίς να σας ρωτήσει."</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Οι εφαρμογές με αυτή την άδεια μπορούν να <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Οι εφαρμογές με αυτή την άδεια έχουν πρόσβαση σε φυσικές δραστηριότητες, όπως το περπάτημα, η ποδηλασία, η οδήγηση, ο αριθμός βημάτων και άλλα"</string>
+ <string name="permission_description_summary_calendar" msgid="103329982944411010">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στο ημερολόγιό σας"</string>
+ <string name="permission_description_summary_call_log" msgid="7321437186317577624">"Οι εφαρμογές με αυτή την άδεια, έχουν δυνατότητα ανάγνωσης και εγγραφής στο αρχείο καταγραφής κλήσεων"</string>
+ <string name="permission_description_summary_camera" msgid="108004375101882069">"Οι εφαρμογές με αυτή την άδεια μπορούν να τραβούν φωτογραφίες και να εγγράφουν βίντεο"</string>
+ <string name="permission_description_summary_contacts" msgid="2337798886460408996">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στις επαφές σας"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στην τοποθεσία αυτής της συσκευής"</string>
+ <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Οι εφαρμογές με αυτή την άδεια μπορούν να βρίσκουν, να συνδέονται και να προσδιορίζουν τη σχετική τοποθεσία κοντινών συσκευών"</string>
+ <string name="permission_description_summary_microphone" msgid="630834800308329907">"Οι εφαρμογές με αυτή την άδεια μπορούν να εγγράφουν ήχο"</string>
+ <string name="permission_description_summary_phone" msgid="4515277217435233619">"Οι εφαρμογές με αυτή την άδεια έχουν δυνατότητα πραγματοποίησης και διαχείρισης τηλεφωνικών κλήσεων"</string>
+ <string name="permission_description_summary_sensors" msgid="1836045815643119949">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στα δεδομένα αισθητήρα σχετικά με τις ζωτικές ενδείξεις σας"</string>
+ <string name="permission_description_summary_sms" msgid="725999468547768517">"Οι εφαρμογές με αυτή την άδεια μπορούν να στέλνουν και να προβάλλουν μηνύματα SMS"</string>
+ <string name="permission_description_summary_storage" msgid="6575759089065303346">"Οι εφαρμογές με αυτή την άδεια έχουν πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας"</string>
+ <string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στη μουσική και σε άλλα αρχεία ήχου αυτής της συσκευής"</string>
+ <string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"Οι εφαρμογές με αυτή την άδεια μπορούν να αποκτήσουν πρόσβαση στις φωτογραφίες και τα βίντεο αυτής της συσκευής"</string>
<string name="app_permission_most_recent_summary" msgid="4292074449384040590">"Τελευταία πρόσβαση: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Απορρίφθηκε αυτήν τη φορά/Τελευταία πρόσβαση: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Δεν έγινε ποτέ πρόσβαση"</string>
@@ -284,7 +284,7 @@
<string name="background_location_access_reminder_notification_content" msgid="7787084707336546245">"Αυτή η εφαρμογή μπορεί να έχει πάντα πρόσβαση στην τοποθεσία σας. Πατήστε για να αλλάξετε τη ρύθμιση."</string>
<string name="notification_listener_reminder_notification_title" msgid="3747210460187479091">"Έλεγχος εφαρμογής που έχει πρόσβαση στις ειδοποιήσεις σας"</string>
<string name="notification_listener_reminder_notification_content" msgid="831476101108863427">"Η εφαρμογή <xliff:g id="APP_NAME">%s</xliff:g> μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους"</string>
- <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"Αυτή η εφαρμογή μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους. Ορισμένες εφαρμογές χρειάζονται αυτήν την πρόσβαση για να λειτουργούν όπως προβλέπεται."</string>
+ <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"Αυτή η εφαρμογή μπορεί να παραβλέψει ειδοποιήσεις, να εκτελέσει ενέργειες σε αυτές και να αποκτήσει πρόσβαση σε περιεχόμενο στο εσωτερικό τους. Ορισμένες εφαρμογές χρειάζονται αυτή την πρόσβαση για να λειτουργούν όπως προβλέπεται."</string>
<string name="notification_listener_remove_access_button_label" msgid="7101898782417817097">"Κατάργηση πρόσβασης"</string>
<string name="notification_listener_review_app_button_label" msgid="3433073281029143924">"Εμφάνιση περισσότερων επιλογών"</string>
<string name="notification_listener_remove_access_success_label" msgid="2477611529875633107">"Η πρόσβαση καταργήθηκε"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Εμφάνιση εντοπισμού ενεργοποίησης βοηθού"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Εμφάνιση εικονιδίου στη γραμμή κατάστασης όταν το μικρόφωνο χρησιμοποιείται για την ενεργοποίηση του φωνητικού βοηθού"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση σε φωτογραφίες και μέσα στη συσκευή σας;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στις επαφές σας;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση στην τοποθεσία αυτής της συσκευής;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Η εφαρμογή θα έχει πρόσβαση στην τοποθεσία μόνο κατά τη διάρκεια χρήσης της εφαρμογής"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στην τοποθεσία αυτής της συσκευής;"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Αυτή η εφαρμογή θέλει να έχει συνεχώς πρόσβαση στην τοποθεσία σας, ακόμη και όταν δεν χρησιμοποιείτε την εφαρμογή. "<annotation id="link">"Εγκρίνετε το αίτημα στις ρυθμίσεις."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Αλλαγή πρόσβασης στην τοποθεσία για την εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;;"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Αυτή η εφαρμογή θέλει να έχει συνεχώς πρόσβαση στην τοποθεσία σας, ακόμη και όταν δεν χρησιμοποιείτε την εφαρμογή. "<annotation id="link">"Εγκρίνετε το αίτημα στις ρυθμίσεις."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Να επιτρέπεται η εύρεση, η σύνδεση κι ο προσδιορισμός σχετικής τοποθεσίας των κοντινών συσκευών από &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Να επιτρέπεται η εύρεση, η σύνδεση κι ο προσδιορισμός σχετικής τοποθεσίας των κοντινών συσκευών από &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;; "<annotation id="link">"Έγκριση στις Ρυθμίσεις."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Αλλαγή της πρόσβασης της εφαρμογής <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> στην τοποθεσία από κατά προσέγγιση σε ακριβή;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στην κατά προσέγγιση τοποθεσία αυτής της συσκευής;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Ακριβής"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Κατά προσέγγιση"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στο ημερολόγιό σας;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η αποστολή και η προβολή μηνυμάτων SMS;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση σε φωτογραφίες, μέσα και αρχεία στη συσκευή σας;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε &lt;b&gt;φωτογραφίες, βίντεο, μουσική και ήχο&lt;/b&gt; της συσκευής;"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε &lt;b&gt;φωτογραφίες, βίντεο, μουσική, ήχο και άλλα αρχεία&lt;/b&gt; της συσκευής;"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση στη μουσική και στα αρχεία ήχου αυτής της συσκευής;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση στις φωτογραφίες και τα βίντεο αυτής της συσκευής;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πρόσβαση σε περισσότερες φωτογραφίες και βίντεο αυτής της συσκευής;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η εγγραφή ήχου;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Αυτή η εφαρμογή θα μπορεί να εγγράφει ήχο μόνο όταν τη χρησιμοποιείτε"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η εγγραφή ήχου;"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Αυτή η εφαρμογή ενδέχεται να εγγράφει βίντεο συνεχώς, ακόμη και όταν δεν τη χρησιμοποιείτε. "<annotation id="link">"Έγκριση στις ρυθμίσεις."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Αλλαγή πρόσβασης στο μικρόφωνο για την εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;;"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Αυτή η εφαρμογή θέλει να εγγράφει ήχο συνεχώς, ακόμη και όταν δεν τη χρησιμοποιείται. "<annotation id="link">"Έγκριση στις ρυθμίσεις."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στη σωματική σας δραστηριότητα;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η λήψη φωτογραφιών και η εγγραφή βίντεο;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Αυτή η εφαρμογή θα μπορεί να τραβάει φωτογραφίες και να εγγράφει βίντεο μόνο όταν τη χρησιμοποιείτε"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η λήψη φωτογραφιών και η εγγραφή βίντεο;"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Αυτή η εφαρμογή ενδέχεται να τραβάει φωτογραφίες και να εγγράφει βίντεο συνεχώς, ακόμη και όταν δεν τη χρησιμοποιείτε. "<annotation id="link">"Έγκριση στις Ρυθμίσεις."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Αλλαγή πρόσβασης στην κάμερα για την εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;;"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Αυτή η εφαρμογή θέλει να τραβάει φωτογραφίες και να εγγράφει βίντεο συνεχώς, ακόμη και όταν δεν τη χρησιμοποιείται. "<annotation id="link">"Έγκριση στις Ρυθμίσεις."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να έχει πρόσβαση στα αρχεία καταγραφής τηλεφωνικών κλήσεών σας;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η πραγματοποίηση και η διαχείριση τηλεφωνικών κλήσεων;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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="6651914048792092835">"Αυτή η εφαρμογή θέλει πρόσβαση στα δεδομένα αισθητήρα για τις ζωτικές σας ενδείξεις, ακόμη και όταν δεν τη χρησιμοποιείτε. Για να κάνετε αυτήν την αλλαγή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
+ <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="7726767635834043501">"Για να επιτρέψετε σε αυτήν την εφαρμογή να έχει πρόσβαση σε δεδομένα αισθητήρων σώματος οποιαδήποτε στιγμή, ακόμα και όταν δεν χρησιμοποιείτε την εφαρμογή, "<annotation id="link">"μεταβείτε στις ρυθμίσεις."</annotation></string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Για να επιτρέψετε σε αυτή την εφαρμογή να έχει πρόσβαση σε δεδομένα αισθητήρων σώματος οποιαδήποτε στιγμή, ακόμα και όταν δεν χρησιμοποιείτε την εφαρμογή, "<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="auto_granted_permissions" msgid="6009452264824455892">"Ελεγχόμενες άδειες"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Να επιτρέπεται στο &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να σας στέλνει ειδοποιήσεις;"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Ελεγχόμενες άδειες"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> έχει πρόσβαση στην τοποθεσία"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Ο οργανισμός σας επιτρέπει στην εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> να έχει πρόσβαση στην τοποθεσία σας"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Άλλες άδειες"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Άδεια που χρησιμοποιείται από το σύστημα"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Άδειες που χρησιμοποιούνται από εφαρμογές του συστήματος."</string>
@@ -542,8 +594,8 @@
<string name="permissions_removed_qs" msgid="8957319130625294572">"Η άδεια καταργήθηκε"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"Προβολή πρόσφατης χρήσης κάμερας"</string>
<string name="microphone_usage_qs" msgid="8527666682168170417">"Προβολή πρόσφατης χρήσης μικροφώνου"</string>
- <string name="remove_camera_qs" msgid="3649996161066883350">"Κατάργηση άδειας για αυτήν την εφαρμογή"</string>
- <string name="remove_microphone_qs" msgid="1276551965129953198">"Κατάργηση άδειας για αυτήν την εφαρμογή"</string>
+ <string name="remove_camera_qs" msgid="3649996161066883350">"Κατάργηση άδειας για αυτή την εφαρμογή"</string>
+ <string name="remove_microphone_qs" msgid="1276551965129953198">"Κατάργηση άδειας για αυτή την εφαρμογή"</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>
@@ -583,7 +635,7 @@
<string name="mic_toggle_title" msgid="2649991093496110162">"Πρόσβαση μικροφώνου"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Για εφαρμογές και υπηρεσίες"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Για εφαρμογές και υπηρεσίες. Εάν είναι απενεργοποιημένη αυτή η ρύθμιση, τα δεδομένα μικροφώνου ενδέχεται να κοινοποιούνται όταν καλείτε έναν αριθμό έκτακτης ανάγκης."</string>
- <string name="location_settings_subtitle" msgid="2328360561197430695">"Εμφάνιση εφαρμογών και υπηρεσιών που έχουν πρόσβαση σε αυτήν την τοποθεσία"</string>
+ <string name="location_settings_subtitle" msgid="2328360561197430695">"Εμφάνιση εφαρμογών και υπηρεσιών που έχουν πρόσβαση σε αυτή την τοποθεσία"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Εμφάνιση πρόσβασης στο πρόχειρο"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Να εμφανίζεται ένα μήνυμα όταν οι εφαρμογές αποκτούν πρόσβαση σε κείμενο, εικόνες ή άλλο περιεχόμενο που έχετε αντιγράψει"</string>
<string name="show_password_title" msgid="2877269286984684659">"Εμφάνιση κωδικών πρόσβασης"</string>
@@ -591,8 +643,9 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Αυτή η εφαρμογή έχει δηλώσει ότι ενδέχεται να κοινοποιήσει δεδομένα τοποθεσίας σε τρίτα μέρη."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Κοινοποίηση δεδομένων και τοποθεσία"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Προέλευση πληροφοριών κοινοποίησης δεδομένων"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Ο προγραμματιστής παρείχε πληροφορίες στον κατασκευαστή της συσκευής για το πώς η εφαρμογή μοιράζεται δεδομένα. Ο προγραμματιστής μπορεί να ενημερώσει αυτές τις πληροφορίες με την πάροδο του χρόνου."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Ο προγραμματιστής έχει καταχωρίσει πληροφορίες στο "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" σχετικά με το πώς αυτή η εφαρμογή κοινοποιεί δεδομένα. Ο προγραμματιστής μπορεί να ενημερώσει αυτές τις πληροφορίες με την πάροδο του χρόνου."</string>
- <string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Η εφαρμ. μπορεί να κοινοποιεί δεδομ. τοποθεσ. για:"</string>
+ <string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Η εφαρμογή μπορεί να κοινοποιεί δεδομένα τοποθεσίας για:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Η κοινοποίηση δεδομένων διαφέρει"</string>
<string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"Οι πρακτικές απορρήτου μπορεί να διαφέρουν ανάλογα με την έκδοση και τη χρήση της εφαρμογής, καθώς και με την περιοχή και την ηλικία σας. "<annotation id="link">"Περισσότερα σχετικά με την κοινοποίηση δεδομένων"</annotation></string>
<string name="permission_rationale_data_sharing_varies_message_without_link" msgid="4912763761399025094">"Οι πρακτικές διαχείρισης δεδομένων μπορεί να διαφέρουν ανάλογα με την έκδοση και τη χρήση της εφαρμογής, καθώς και με την περιοχή και την ηλικία σας."</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Ασφάλεια δεδομένων"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Τα δεδομένα τοποθεσίας ενδέχεται να κοινοποιούνται"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Αυτή η εφαρμογή έχει δηλώσει ότι ενδέχεται να κοινοποιήσει τα δεδομένα τοποθεσίας σας σε τρίτα μέρη"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Δεν είναι δυνατό το άνοιγμα αυτού του συνδέσμου"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Ενημερώσεις στην κοινοποίηση δεδ. για τοποθεσία"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Ελέγξτε εφαρμογές που άλλαξαν τον τρόπο με τον οποίο ενδέχεται να κοινοποιούν τα δεδομένα τοποθεσίας"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Αυτές οι εφαρμογές έχουν αλλάξει τον τρόπο με τον οποίο μπορούν να κοινοποιούν τα δεδομένα τοποθεσία σας. Ενδέχεται να μην τα έχουν κοινοποιήσει στο παρελθόν ή να τα κοινοποιούν τώρα για σκοπούς διαφήμισης ή μάρκετινγκ."</string>
diff --git a/PermissionController/res/values-en-rAU/strings.xml b/PermissionController/res/values-en-rAU/strings.xml
index 513db22f7..ecd75e3dd 100644
--- a/PermissionController/res/values-en-rAU/strings.xml
+++ b/PermissionController/res/values-en-rAU/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Show assistant trigger detection"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Show icon in status bar when microphone is used to activate voice assistant"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; location?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"The app will only have access to the location while you\'re using the app"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s location?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"This app may want to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"This app wants to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in Settings."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices? "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access from approximate to precise?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; from approximate to precise?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s approximate location?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;’s approximate location?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precise"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximate"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music and audio&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music, audio and other files&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"The app will only be able to record audio while you’re using the app"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"This app may want to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"This app wants to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"The app will only be able to take pictures and record video while you’re using the app"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"This app may want to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"This app wants to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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_device_aware_phone" msgid="4389610977195521813">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"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 on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> has location access"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Your organisation allows <xliff:g id="APP_NAME">%1$s</xliff:g> to access your location"</string>
@@ -520,7 +547,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"For apps and services"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Microphone data may still be shared when you call an emergency number."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Change"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security &amp; privacy"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security and privacy"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Scan device"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Dismiss"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Dismiss this alert?"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"This app stated that it may share location data with third parties"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Data sharing and location"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Where data sharing info comes from"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"The developer provided info to this device\'s manufacturer about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"The developer provided info to "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"This app may share location data for:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Data sharing varies"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Data safety"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Location data may be shared"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"This app stated that it may share your location data with third parties"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Can’t open this link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Data sharing updates for location"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Review apps that changed the way that they may share your location data"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"These apps have changed the way that they may share your location data. They may not have shared it before or may now share it for advertising or marketing purposes."</string>
diff --git a/PermissionController/res/values-en-rCA/strings.xml b/PermissionController/res/values-en-rCA/strings.xml
index e3a42643f..e5a3ac944 100644
--- a/PermissionController/res/values-en-rCA/strings.xml
+++ b/PermissionController/res/values-en-rCA/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Show assistant trigger detection"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Show icon in status bar when microphone is used to activate voice assistant"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; location?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"The app will only have access to the location while you\'re using the app"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s location?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"This app may want to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"This app wants to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices? "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access from approximate to precise?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; from approximate to precise?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s approximate location?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;’s approximate location?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precise"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximate"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media, and files on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media, and files on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music, and audio&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music, audio, and other files&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"The app will only be able to record audio while you’re using the app"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"This app may want to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"This app wants to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"The app will only be able to take pictures and record video while you’re using the app"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"This app may want to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"This app wants to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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_device_aware_phone" msgid="4389610977195521813">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"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 on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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 app is in use?"</string>
+ <string name="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> has location access"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Your organization allows <xliff:g id="APP_NAME">%1$s</xliff:g> to access your location"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"This app stated it may share location data with third parties"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Data sharing and location"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Where data sharing info comes from"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"The developer provided info to this device\'s manufacturer about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"The developer provided info to "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"This app may share location data for:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Data sharing varies"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Data safety"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Location data may be shared"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"This app stated it may share your location data with third parties"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Can’t open this link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Data sharing updates for location"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Review apps that changed the way they may share your location data"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"These apps have changed the way they may share your location data. They may not have shared it before, or may now share it for advertising or marketing purposes."</string>
diff --git a/PermissionController/res/values-en-rGB/strings.xml b/PermissionController/res/values-en-rGB/strings.xml
index bb0c0f203..052c3a3d9 100644
--- a/PermissionController/res/values-en-rGB/strings.xml
+++ b/PermissionController/res/values-en-rGB/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Show assistant trigger detection"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Show icon in status bar when microphone is used to activate voice assistant"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; location?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"The app will only have access to the location while you’re using the app"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s location?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"This app may want to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"This app wants to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in Settings."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices? "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access from approximate to precise?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; from approximate to precise?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s approximate location?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;’s approximate location?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precise"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximate"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music and audio&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music, audio and other files&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"The app will only be able to record audio while you’re using the app"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"This app may want to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"This app wants to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"The app will only be able to take pictures and record video while you’re using the app"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"This app may want to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"This app wants to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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_device_aware_phone" msgid="4389610977195521813">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"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 on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> has location access"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Your organisation allows <xliff:g id="APP_NAME">%1$s</xliff:g> to access your location"</string>
@@ -520,7 +547,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"For apps and services"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Microphone data may still be shared when you call an emergency number."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Change"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security &amp; privacy"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security and privacy"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Scan device"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Dismiss"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Dismiss this alert?"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"This app stated that it may share location data with third parties"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Data sharing and location"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Where data sharing info comes from"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"The developer provided info to this device\'s manufacturer about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"The developer provided info to "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"This app may share location data for:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Data sharing varies"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Data safety"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Location data may be shared"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"This app stated that it may share your location data with third parties"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Can’t open this link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Data sharing updates for location"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Review apps that changed the way that they may share your location data"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"These apps have changed the way that they may share your location data. They may not have shared it before or may now share it for advertising or marketing purposes."</string>
diff --git a/PermissionController/res/values-en-rIN/strings.xml b/PermissionController/res/values-en-rIN/strings.xml
index bb0c0f203..052c3a3d9 100644
--- a/PermissionController/res/values-en-rIN/strings.xml
+++ b/PermissionController/res/values-en-rIN/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Show assistant trigger detection"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Show icon in status bar when microphone is used to activate voice assistant"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and media on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your contacts on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; location?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"The app will only have access to the location while you’re using the app"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s location?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s location?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"This app may want to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Change location access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"This app wants to access your location all the time, even when you’re not using the app. "<annotation id="link">"Allow in Settings."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to find, connect to and determine the relative position of nearby devices? "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access from approximate to precise?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Change <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>’s location access on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; from approximate to precise?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access this device’s approximate location?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;’s approximate location?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precise"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximate"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your calendar on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send and view SMS messages on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your device?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos, media and files on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music and audio&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access &lt;b&gt;photos, videos, music, audio and other files&lt;/b&gt; on this device?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access music and audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on this device?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access more photos and videos on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"The app will only be able to record audio while you’re using the app"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"This app may want to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Change microphone access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"This app wants to record audio all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your physical activity on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"The app will only be able to take pictures and record video while you’re using the app"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"This app may want to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Change camera access for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"This app wants to take pictures and record video all the time, even when you’re not using the app. "<annotation id="link">"Allow in settings."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access your phone call logs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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_device_aware_phone" msgid="4389610977195521813">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to make and manage phone calls on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access sensor data about your vital signs on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"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 on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Keep allowing &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to access body sensor data on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to send you notifications on your &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Controlled permissions"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> has location access"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Your organisation allows <xliff:g id="APP_NAME">%1$s</xliff:g> to access your location"</string>
@@ -520,7 +547,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"For apps and services"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Microphone data may still be shared when you call an emergency number."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Change"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security &amp; privacy"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Security and privacy"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Scan device"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Dismiss"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Dismiss this alert?"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"This app stated that it may share location data with third parties"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Data sharing and location"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Where data sharing info comes from"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"The developer provided info to this device\'s manufacturer about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"The developer provided info to "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" about how this app shares data. The developer may update this info over time."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"This app may share location data for:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Data sharing varies"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Data safety"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Location data may be shared"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"This app stated that it may share your location data with third parties"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Can’t open this link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Data sharing updates for location"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Review apps that changed the way that they may share your location data"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"These apps have changed the way that they may share your location data. They may not have shared it before or may now share it for advertising or marketing purposes."</string>
diff --git a/PermissionController/res/values-en-rXC/strings.xml b/PermissionController/res/values-en-rXC/strings.xml
index bf63f7ab4..785f2f8fc 100644
--- a/PermissionController/res/values-en-rXC/strings.xml
+++ b/PermissionController/res/values-en-rXC/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎Show assistant trigger detection‎‏‎‎‏‎"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎Show icon in status bar when microphone is used to activate voice assistant‎‏‎‎‏‎"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos and media on your device?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos and media on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your contacts?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your contacts on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access this device’s location?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎’s&lt;/b&gt; location?‎‏‎‎‏‎"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎The app will only have access to the location while you’re using the app‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access this device’s location?‎‏‎‎‏‎"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%2$s</xliff:g>‎‏‎‎‏‏‏‎’s location?‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎This app may want to access your location all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‎Change location access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‎‏‎Change location access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎This app wants to access your location all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to find, connect to, and determine the relative position of nearby devices? ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎Change ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>‎‏‎‎‏‏‏‎’s location access from approximate to precise?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎Change ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>‎‏‎‎‏‏‏‎’s location access on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; from approximate to precise?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access this device’s approximate location?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;’s approximate location?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎Precise‎‏‎‎‏‎"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎Approximate‎‏‎‎‏‎"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your calendar?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your calendar on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to send and view SMS messages?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‏‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to send and view SMS messages on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos, media, and files on your device?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos, media, and files on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access &lt;b&gt;photos, videos, music, and audio&lt;/b&gt; on this device?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access &lt;b&gt;photos, videos, music, audio, and other files&lt;/b&gt; on this device?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access music and audio on this device?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access music and audio on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos and videos on this device?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access photos and videos on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access more photos and videos on this device?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access more photos and videos on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to record audio?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to record audio on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎The app will only be able to record audio while you’re using the app‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to record audio?‎‏‎‎‏‎"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to record audio on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎This app may want to record audio all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎Change microphone access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎Change microphone access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎This app wants to record audio all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your physical activity?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your physical activity on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to take pictures and record video?‎‏‎‎‏‎"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to take pictures and record video on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‏‎The app will only be able to take pictures and record video while you’re using the app‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to take pictures and record video?‎‏‎‎‏‎"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to take pictures and record video on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎This app may want to take pictures and record video all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎Change camera access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‎‎Change camera access for &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎‏‎‏‎This app wants to take pictures and record video all the time, even when you’re not using the app. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Allow in settings.‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
<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_device_aware_calllog" msgid="735079772627778095">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access your phone call logs on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</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_device_aware_phone" msgid="4389610977195521813">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to make and manage phone calls on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access sensor data about your vital signs on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎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 on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎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 app is in use?‎‏‎‎‏‎"</string>
+ <string name="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‏‎Keep allowing &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to access body sensor data on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to send you notifications on your &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎Controlled permissions‎‏‎‎‏‎"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ has location access‎‏‎‎‏‎"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‎Your organization allows ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to access your location‎‏‎‎‏‎"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎This app stated it may share location data with third parties‎‏‎‎‏‎"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎Data sharing and location‎‏‎‎‏‎"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎Where data sharing info comes from‎‏‎‎‏‎"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎The developer provided info to this device\'s manufacturer about how this app shares data. The developer may update this info over time.‎‏‎‎‏‎"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎The developer provided info to ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"<annotation id="install_source" example="App Store">"‎‏‎‎‏‏‏‎%1$s‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎ about how this app shares data. The developer may update this info over time.‎‏‎‎‏‎"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎This app may share location data for:‎‏‎‎‏‎"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎Data sharing varies‎‏‎‎‏‎"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎Data safety‎‏‎‎‏‎"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‎Location data may be shared‎‏‎‎‏‎"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎This app stated it may share your location data with third parties‎‏‎‎‏‎"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎Can’t open this link‎‏‎‎‏‎"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‏‎Data sharing updates for location‎‏‎‎‏‎"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‎‏‎Review apps that changed the way they may share your location data‎‏‎‎‏‎"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎These apps have changed the way they may share your location data. They may not have shared it before, or may now share it for advertising or marketing purposes.‎‏‎‎‏‎"</string>
diff --git a/PermissionController/res/values-es-rUS-v33/strings.xml b/PermissionController/res/values-es-rUS-v33/strings.xml
index 5aeea4db3..0205fca80 100644
--- a/PermissionController/res/values-es-rUS-v33/strings.xml
+++ b/PermissionController/res/values-es-rUS-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Más alertas"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertas descartadas"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Expande y ve una alerta más}many{Expande y ve # de alertas más}other{Expande y ve # alertas más}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta: <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Se completó la acción"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Revisa los parámetros de configuración que pueden proteger aún más tu dispositivo"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Configuración rápida de parámetros de seguridad y privacidad"</string>
diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml
index fa0201af9..07a5ff529 100644
--- a/PermissionController/res/values-es-rUS/strings.xml
+++ b/PermissionController/res/values-es-rUS/strings.xml
@@ -41,7 +41,7 @@
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Ignorar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="permission_warning_template" msgid="2247087781222679458">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; realice la siguiente acción: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pueda <xliff:g id="ACTION">%2$s</xliff:g> siempre?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siempre pueda realizar la siguiente acción: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Solo cuando se usa la app"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Siempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"No permitir y no volver a preguntar"</string>
@@ -130,8 +130,8 @@
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Ver otros permisos"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> y <xliff:g id="NUM">%3$s</xliff:g> más"</string>
- <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Cronograma de cuándo las apps usaron tu <xliff:g id="PERMGROUP">%1$s</xliff:g> durante las últimas 24 horas"</string>
- <string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"Cronograma de cuándo las apps usaron tu <xliff:g id="PERMGROUP">%1$s</xliff:g> durante los últimos 7 días"</string>
+ <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Cronología de cuándo las apps usaron tu <xliff:g id="PERMGROUP">%1$s</xliff:g> durante las últimas 24 horas"</string>
+ <string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"Cronología de cuándo las apps usaron tu <xliff:g id="PERMGROUP">%1$s</xliff:g> durante los últimos 7 días"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"Cuándo esta app usó tu permiso de <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="permission_usage_access_dialog_learn_more" msgid="7121468469493184613">"Más información"</string>
<string name="learn_more_content_description" msgid="8673699744544502539">"Más información sobre <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
@@ -424,7 +424,7 @@
<string name="default_apps" msgid="5119201969348748639">"Apps predeterminadas"</string>
<string name="no_default_apps" msgid="2593466527182950231">"Sin apps predeterminadas"</string>
<string name="default_apps_more" msgid="4078194675848858093">"Más apps predeterminadas"</string>
- <string name="default_apps_manage_domain_urls" msgid="6775566451561036069">"Vínculos de apertura"</string>
+ <string name="default_apps_manage_domain_urls" msgid="6775566451561036069">"Abrir vínculos"</string>
<string name="default_apps_for_work" msgid="4970308943596201811">"Predeterminadas de trabajo"</string>
<string name="default_app_none" msgid="9084592086808194457">"Ninguna"</string>
<string name="default_app_system_default" msgid="6218386768175513760">"(Predeterminada de sistema)"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostrar detección de activación de asistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostrar ícono en la barra de estado cuando se use el micrófono para activar la función \"Asistente de voz\""</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos y el contenido multimedia del dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tus contactos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"La app solo tendrá acceso a la ubicación cuando esté en uso"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación de este dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Es posible que esta app quiera acceder a tu ubicación todo el tiempo, incluso cuando no la uses. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"¿Quieres cambiar el acceso a la ubicación de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Esta app quiere acceder a tu ubicación todo el tiempo, incluso cuando no la uses. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encuentre dispositivos cercanos, se conecte a ellos y determine su ubicación relativa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encuentre dispositivos cercanos, se conecte a ellos y determine su ubicación relativa? "<annotation id="link">"Hazlo en Configuración."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"¿Quieres cambiar el acceso a la ubicación de <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> de aproximada a precisa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"¿Deseas permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación aproximada de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precisa"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu calendario?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envíe y vea SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos, el contenido multimedia y los archivos de tu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a &lt;b&gt;fotos, videos, música y audio&lt;/b&gt; del dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a &lt;b&gt;fotos, videos, música, audio y otros archivos&lt;/b&gt; del dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la música y los archivos de audio de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos y los videos de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a más fotos y videos del dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"La app solo podrá grabar audio cuando esté en uso"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Es posible que esta app quiera grabar audio todo el tiempo, incluso cuando no la estés usando. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"¿Cambiar el acceso al micrófono de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Esta app quiere grabar audio todo el tiempo, incluso cuando no la uses. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu actividad física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tome fotos y grabe videos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"La app solo podrá tomar fotos y grabar videos cuando esté en uso"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tome fotos y grabe videos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Es posible que esta app quiera tomar fotos y grabar videos todo el tiempo, incluso cuando no la estés usando. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"¿Cambiar el acceso a la cámara de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Esta app quiere tomar fotos y grabar videos todo el tiempo, incluso cuando no la uses. "<annotation id="link">"Permite el acceso en Configuración."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> tiene acceso a la ubicación"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Tu organización permite que <xliff:g id="APP_NAME">%1$s</xliff:g> acceda a tu ubicación"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Otros permisos"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Permiso que usa el sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Permisos que usan solo las aplicaciones del sistema."</string>
@@ -515,7 +567,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"Últimas\n24 horas"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Últimos\n7 días"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en la barra de estado ni en el panel de privacidad."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"protege <xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en la barra de estado ni en el panel de privacidad."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> está protegida por Android. Tus datos se procesan en este dispositivo, por eso no se muestra el uso de permisos de esta app en el panel de privacidad."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"La cámara del dispositivo está bloqueada"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"El micrófono del dispositivo está bloqueado"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"La ubicación del dispositivo está desactivada"</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"Para apps y servicios. Aunque se desactive este parámetro de configuración, es posible que se sigan compartiendo los datos del micrófono cuando llames a un número de emergencia."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Consulta las apps y los servicios que tienen acceso a la ubicación"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Mostrar acceso a portapapeles"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Mostrar un mensaje cuando las apps accedan a textos, imágenes y otro contenido que hayas copiado"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Muestra un mensaje cuando las apps accedan a texto, imágenes y otro contenido que hayas copiado"</string>
<string name="show_password_title" msgid="2877269286984684659">"Mostrar contraseñas"</string>
<string name="show_password_summary" msgid="1110166488865981610">"Mostrar caracteres brevemente mientras escribes"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Esta app indicó que podría compartir datos de ubicación con terceros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Uso compartido de datos y ubicación"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De dónde proviene la información de uso compartido de datos"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"El desarrollador brindó información al fabricante del dispositivo sobre el uso compartido de datos de esta app. El desarrollador podría actualizar esta información con el tiempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"El desarrollador brindó información a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre el uso compartido de datos de esta app. El desarrollador podría actualizar esta información con el tiempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Esta app puede compartir datos de ubicación para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"El uso compartido de datos varía"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Seguridad de los datos"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Es posible que se compartan los datos de ubicación"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Esta app indicó que podría compartir tus datos de ubicación con terceros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"No se puede abrir este vínculo"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Actualizaciones del uso compartido de los datos de ubicación"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Revisa las apps que cambiaron la forma en que comparten tus datos de ubicación"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Estas apps cambiaron la forma en que podrían compartir tus datos de ubicación. Es posible que no los hayan compartido antes o que ahora los compartan con fines publicitarios o de marketing."</string>
diff --git a/PermissionController/res/values-es-v33/strings.xml b/PermissionController/res/values-es-v33/strings.xml
index 4f50aaa25..69b1ce6f5 100644
--- a/PermissionController/res/values-es-v33/strings.xml
+++ b/PermissionController/res/values-es-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Más alertas"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertas ignoradas"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Ampliar para ver una alerta más}many{Ampliar para ver # alertas más}other{Ampliar para ver # alertas más}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Acción completada"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Comprueba los ajustes que pueden proteger más tu dispositivo"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Ajustes rápidos de seguridad y privacidad"</string>
diff --git a/PermissionController/res/values-es/strings.xml b/PermissionController/res/values-es/strings.xml
index 951e5b10b..4db824b56 100644
--- a/PermissionController/res/values-es/strings.xml
+++ b/PermissionController/res/values-es/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"No permitir de todas formas"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Cerrar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"¿Permitir a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"¿Quieres permitir siempre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"¿Permitir a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lo siguiente? <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"¿Permitir siempre a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lo siguiente? <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Solo mientras se usa la aplicación"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Siempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"No permitir y no volver a preguntar"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Se abrió por última vez el <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Si permites la gestión de todos los archivos, esta aplicación podrá consultar, modificar y eliminar cualquier archivo que haya en el almacenamiento común de este dispositivo o en los dispositivos de almacenamiento conectados. Es posible que acceda a archivos sin preguntarte."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"¿Permitir que esta aplicación pueda consultar, modificar y eliminar archivos de este dispositivo o de los dispositivos de almacenamiento conectados? Quizá acceda a archivos sin solicitarlo explícitamente."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Las aplicaciones con este permiso pueden <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Las aplicaciones con este permiso pueden hacer lo siguiente: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Las aplicaciones con este permiso pueden acceder a tu actividad física, como paseos a pie o en bici, trayectos en coche, número de pasos y más"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Las aplicaciones con este permiso pueden acceder a tu calendario"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Las aplicaciones con este permiso pueden leer y editar el registro de llamadas del teléfono"</string>
@@ -246,12 +246,12 @@
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"No ha accedido nunca"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"Denegado / Último acceso: Nunca"</string>
<string name="allowed_header" msgid="7769277978004790414">"Permitido"</string>
- <string name="allowed_always_header" msgid="6455903312589013545">"Permitido siempre"</string>
+ <string name="allowed_always_header" msgid="6455903312589013545">"Permitidas siempre"</string>
<string name="allowed_foreground_header" msgid="6845655788447833353">"Permitidas solo mientras se usan"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Pueden acceder solo al contenido multimedia"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Pueden gestionar todos los archivos"</string>
<string name="ask_header" msgid="2633816846459944376">"Preguntar siempre"</string>
- <string name="denied_header" msgid="903209608358177654">"No permitido"</string>
+ <string name="denied_header" msgid="903209608358177654">"No permitidas"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"Ver más aplicaciones que pueden acceder a todos los archivos"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 día}many{# días}other{# días}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# hora}many{# horas}other{# horas}}"</string>
@@ -347,7 +347,7 @@
<string name="accessibility_service_dialog_title_multiple" msgid="5527879210683548175">"<xliff:g id="NUM_SERVICES">%s</xliff:g> aplicaciones de accesibilidad tienen acceso completo a tu dispositivo"</string>
<string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"<xliff:g id="SERVICE_NAME">%s</xliff:g> puede ver tu pantalla, lo que haces y lo que introduces; realizar acciones; y controlar la pantalla."</string>
<string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"Estas aplicaciones pueden ver tu pantalla, lo que haces y lo que introduces; realizar acciones; y controlar la pantalla."</string>
- <string name="role_assistant_label" msgid="4727586018198208128">"Asistente digital predeterminado"</string>
+ <string name="role_assistant_label" msgid="4727586018198208128">"Asistente predeterminado"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"Asistente digital"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"Las aplicaciones de asistencia te ayudan según la información que aparezca en la pantalla. Algunas aplicaciones admiten tanto el menú de aplicaciones como los servicios de entrada de voz para ofrecerte asistencia integrada."</string>
<string name="role_browser_label" msgid="2877796144554070207">"Aplicación de navegador predeterminada"</string>
@@ -397,7 +397,7 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y acceder a tu teléfono, SMS, contactos y calendario."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> podrá interactuar con tus notificaciones y reproducir tus aplicaciones en el dispositivo conectado."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Este servicio comparte las fotos, el contenido multimedia y las notificaciones de tu teléfono con otros dispositivos."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"App de notas predeterminada"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"Aplicación de notas predeterminada"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Aplicación de notas"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Aplicaciones que te permiten tomar notas en tu dispositivo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notas"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostrar la detección de activación del asistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostrar icono en la barra de estado cuando se utilice el micrófono para activar el asistente de voz"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos y archivos multimedia del dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tus contactos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"La aplicación solo podrá acceder a la ubicación cuando la estés usando"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación de este dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Es posible que esta aplicación quiera acceder a tu ubicación siempre, aunque no la estés usando. Puedes darle permiso en "<annotation id="link">"Ajustes"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"¿Quieres cambiar el acceso a la ubicación de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Esta aplicación quiere acceder a tu ubicación siempre, incluso aunque no la estés usando. Puedes darle permiso en "<annotation id="link">"Ajustes"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; busque, se conecte y determine la posición relativa de dispositivos cercanos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; busque, se conecte y determine la posición relativa de dispositivos cercanos? "<annotation id="link">"Permítelo en los ajustes"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"¿Cambiar el acceso a la ubicación de <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> de aproximada a precisa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la ubicación aproximada de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precisa"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu calendario?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envíe y lea mensajes SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos, al contenido multimedia y a los archivos de tu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a &lt;b&gt;fotos, vídeos, música y audio&lt;/b&gt; de este dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a &lt;b&gt;fotos, vídeos, música, audio y otros archivos&lt;/b&gt; del dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a música y audio de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a fotos y vídeos de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a más fotos y vídeos de este dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"La aplicación solo podrá grabar audio mientras la estés usando."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Es posible que esta aplicación deba grabar audio en todo momento, aunque no se esté usando. Puedes darle este permiso en "<annotation id="link">"Ajustes."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"¿Quieres cambiar el acceso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; al micrófono?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Esta aplicación debe grabar audio en todo momento, aunque no la estés usando. "<annotation id="link">"Puedes darle este permiso en Ajustes."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a tu actividad física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga fotos y grabe vídeos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"La aplicación solo podrá hacer fotografías y grabar vídeos mientras la estés usando."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga fotos y grabe vídeos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Es posible que esta aplicación deba hacer fotografías y grabar vídeos en todo momento, aunque no se esté usando. "<annotation id="link">"Puedes darle este permiso en Ajustes."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"¿Quieres cambiar el acceso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a la cámara?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Esta aplicación debe hacer fotografías y grabar vídeos en todo momento, aunque no la estés usando. "<annotation id="link">"Puedes darle este permiso en Ajustes."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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">"¿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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Para permitir que esta aplicación acceda a datos de sensores corporales todo el tiempo, incluso cuando no la uses, "<annotation id="link">"ve a los ajustes"</annotation>"."</string>
<string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"¿Seguir permitiendo que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a los datos de los sensores corporales mientras se usa?"</string>
- <string name="permgrouprequest_notifications" msgid="6396739062335106181">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; te envíe notificaciones?"</string>
- <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; te envíe notificaciones?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> tiene acceso a la ubicación"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Tu organización permite que <xliff:g id="APP_NAME">%1$s</xliff:g> acceda a tu ubicación"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Otros permisos"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Permiso usado por el sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Permisos usados solo por las aplicaciones del sistema."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Esta aplicación ha indicado que puede compartir datos de ubicación con terceros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datos compartidos y ubicación"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De dónde procede la información sobre cómo se comparten los datos"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"El desarrollador ha proporcionado información al fabricante de este dispositivo sobre cómo comparte datos esta aplicación. Es posible que el desarrollador actualice esta información con el tiempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"El desarrollador ha proporcionado información a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre cómo comparte datos esta aplicación. Es posible que el desarrollador actualice esta información con el tiempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Esta app puede compartir datos de ubicación para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"La forma de compartir datos varía"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Seguridad de los datos"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Tus datos de ubicación pueden compartirse"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Esta aplicación ha indicado que es posible que comparta tus datos de ubicación con terceros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"No se puede abrir este enlace"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Cambios en los datos compartidos de ubicación"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Consulta las aplicaciones que han cambiado cómo comparten tus datos de ubicación"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Estas aplicaciones han cambiado cómo pueden compartir tus datos de ubicación. Puede que no los hayan compartido antes, o que ahora lo hagan con fines publicitarios o de marketing."</string>
diff --git a/PermissionController/res/values-et-v34/strings.xml b/PermissionController/res/values-et-v34/strings.xml
index 91567dd9e..4476aecdd 100644
--- a/PermissionController/res/values-et-v34/strings.xml
+++ b/PermissionController/res/values-et-v34/strings.xml
@@ -22,6 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"Saate hallata rakenduse juurdepääsu terviseandmetele"</string>
<string name="location_settings" msgid="8863940440881290182">"Juurdepääs asukohale"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Rakenduste ja teenuste jaoks. Isegi kui see seade on välja lülitatud, võidakse mikrofoni andmeid siiski jagada hädaabinumbrile helistades"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Rakenduste ja teenuste jaoks. Isegi kui see seade on välja lülitatud, võidakse mikrofoni andmeid siiski jagada hädaabinumbrile helistades."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Rakenduste ja teenuste jaoks"</string>
</resources>
diff --git a/PermissionController/res/values-et/strings.xml b/PermissionController/res/values-et/strings.xml
index d6c2e7f26..75a4b14e3 100644
--- a/PermissionController/res/values-et/strings.xml
+++ b/PermissionController/res/values-et/strings.xml
@@ -32,7 +32,7 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"Säilita valik „Rakenduse kasutamise ajal”"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"Säilita ainult sel korral"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Lisateave"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Luba kõik"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Anna juurdepääs kõigile"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Luba alati kõik"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Valige fotod ja videod"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Valige rohkem"</string>
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ära luba ikkagi"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Loobu"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Kas lubada rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul toiming <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Kas lubada rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul alati toiming <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Kas lubada rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul luba <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Kas lubada rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul alati luba <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Ainult rakenduse kasutamisel"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Alati"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Ära luba ja ära enam küsi"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Luba alati"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Luba rakenduse kasutamise ajal"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Luba ainult rakenduse kasutamise ajal"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Ära luba"</string>
<string name="loading" msgid="4789365003890741082">"Laadimine …"</string>
<string name="all_permissions" msgid="6911125611996872522">"Kõik load"</string>
@@ -187,7 +187,7 @@
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Luba kõikide failide haldamine"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Luba juurdepääs ainult meediale"</string>
<string name="app_permission_button_allow_always" msgid="4573292371734011171">"Luba alati"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Luba rakenduse kasutamise ajal"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Luba ainult rakenduse kasutamise ajal"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Luba alati kõik"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Küsi iga kord"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Ära luba"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Assistendi käivitamise tuvastamise kuvamine"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Ikooni kuvamine olekuribal, kui häälassistendi aktiveerimiseks kasutatakse mikrofoni"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs seadmes olevatele fotodele ja meediale?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs teie kontaktidele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs selle seadme asukohale?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Rakendusel on juurdepääs asukohale vaid sel ajal, kui rakendust kasutate"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs selle seadme asukohale?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"See rakendus võib soovida pidevat juurdepääsu teie asukohale (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Kas muuta rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul juurdepääsu asukohale?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"See rakendus soovib pidevat juurdepääsu teie asukohale (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; leida lähedalasuvaid seadmeid, nendega ühendada ja nende suhteline asukoht määrata?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; leida lähedalasuvaid seadmeid, nendega ühendada ja nende suhteline asukoht määrata? "<annotation id="link">"Lubage menüüs Seaded."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Kas muuta rakenduse <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> asukohale juurdepääsemise tase ligikaudsest täpseks?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs selle seadme ligikaudsele asukohale?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Täpne"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Ligikaudne"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs teie kalendrile?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; saata ja vaadata SMS-sõnumeid?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Kas lubada rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs seadmes olevatele fotodele, meediale ja failidele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Kas anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt seadmes juurdep. &lt;b&gt;fotodele, videotele, muusikale ja helidele&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdep. &lt;b&gt;foto-, video-, muusika-, heli- ja muudele failidele&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Kas anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; selles seadmes juurdepääs muusikale ja helifailidele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Kas anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; selles seadmes juurdepääs fotodele ja videotele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Kas anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; selles seadmes juurdepääs rohkematele fotodele ja videotele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; salvestada heli?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Rakendus saab heli salvestada vaid siis, kui rakendust kasutate"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; heli salvestada?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"See rakendus võib soovida heli salvestada mis tahes ajal (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Kas muuta rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul juurdepääsu mikrofonile?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"See rakendus soovib heli salvestada mis tahes ajal (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Kas anda rakendusele &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; juurdepääs teie füüsilisele tegevusele?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; jäädvustada pilte ja salvestada videoid?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Rakendus saab pildistada ja videoid salvestada vaid siis, kui rakendust kasutate"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pildistada ja videoid salvestada?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"See rakendus võib soovida pildistada ja videoid salvestada mis tahes ajal (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Kas muuta rakenduse &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; puhul juurdepääsu kaamerale?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"See rakendus soovib pildistada ja videoid salvestada mis tahes ajal (ka siis, kui te rakendust ei kasuta). "<annotation id="link">"Lubage see seadetes."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Hallatud load"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> pääseb juurde asukohale"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Teie organisatsioon lubab rakendusel <xliff:g id="APP_NAME">%1$s</xliff:g> pääseda juurde teie asukohale."</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"See rakendus andis teada, et võib asukohaandmeid jagada kolmandate osapooltega"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Andmete jagamine ja asukoht"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Andmete jagamise teabe päritolu"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Arendaja on esitanud selle seadme tootjale teavet selle kohta, kuidas see rakendus andmeid jagab. Arendaja võib seda teavet aja jooksul muuta."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Arendaja on esitanud rakenduste poele "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" teavet selle kohta, kuidas see rakendus andmeid jagab. Arendaja võib seda teavet aja jooksul muuta."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Rakendus võib asukohaandmeid jagada järgmiseks."</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Andmete jagamine võib olla erinev"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Andmete ohutus"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Asukohaandmeid võidakse jagada"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"See rakendus andis teada, et võib jagada teie asukohaandmeid kolmandate osapooltega."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Seda linki ei saa avada"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Andmete jagamise värskendused asukoha kohta"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Vaadake üle rakendused, mis on muutnud teie asukohaandmete jagamise viisi"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Need rakendused on muutnud teie asukohaandmete jagamise viisi. Võib-olla ei jaganud nad neid varem või hakkasid neid nüüd jagama reklaami- või turunduseesmärgil."</string>
diff --git a/PermissionController/res/values-eu-v33/strings.xml b/PermissionController/res/values-eu-v33/strings.xml
index c9f8903f6..424feaf4a 100644
--- a/PermissionController/res/values-eu-v33/strings.xml
+++ b/PermissionController/res/values-eu-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Alerta gehiago"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Baztertutako alertak"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Zabaldu eta ikusi beste alerta bat}other{Zabaldu eta ikusi # alerta gehiago}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Osatu da ekintza"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Egiaztatu gailuaren segurtasuna hobe dezaketen ezarpenak"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Segurtasunari eta pribatutasunari buruzko ezarpen bizkorrak"</string>
diff --git a/PermissionController/res/values-eu/strings.xml b/PermissionController/res/values-eu/strings.xml
index 5f8f8991e..8674191f2 100644
--- a/PermissionController/res/values-eu/strings.xml
+++ b/PermissionController/res/values-eu/strings.xml
@@ -40,7 +40,7 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ez eman baimenik halere"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Baztertu"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioak <xliff:g id="ACTION">%2$s</xliff:g> ahal izatea baimendu nahi duzu?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari \"<xliff:g id="ACTION">%2$s</xliff:g>\" baimena eman nahi diozu?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"Beti eman nahi diozu \"<xliff:g id="ACTION">%2$s</xliff:g>\" baimena &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Aplikazioa erabiltzean soilik"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Beti"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Eman baimena beti"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Aplikazioa erabiltzean soilik"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Baimendu aplikazioa erabiltzean soilik"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Ez eman baimenik"</string>
<string name="loading" msgid="4789365003890741082">"Kargatzen…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Baimen guztiak"</string>
@@ -126,7 +126,7 @@
<string name="app_name_unknown" msgid="1319665005754048952">"Ezezaguna"</string>
<string name="permission_usage_title" msgid="1568233336351734538">"Pribatutasun-panela"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Ikusi zein aplikaziok erabili berri dituzten baimenak"</string>
- <string name="permission_group_usage_title" msgid="2595013198075285173">"<xliff:g id="PERMGROUP">%1$s</xliff:g> atzitzeko baimenaren erabilera"</string>
+ <string name="permission_group_usage_title" msgid="2595013198075285173">"<xliff:g id="PERMGROUP">%1$s</xliff:g> erabiltzeko baimenaren erabilera"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Ikusi beste baimen batzuk"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> eta beste <xliff:g id="NUM">%3$s</xliff:g>"</string>
@@ -163,7 +163,7 @@
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Azken minutuan baimenei eman zaien erabilera"</string>
<string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{Ez da erabili azken # egunean}other{Ez da erabili azken # egunetan}}"</string>
<string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{Ez da erabili azken # orduan}other{Ez da erabili azken # orduetan}}"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Aplikazio batek erabili du}other{# aplikaziok erabili dute}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{1 aplikaziok erabili du}other{# aplikaziok erabili dute}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Ikusi guztiak panelean"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Iragazteko irizpidea: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"Kendu iragazkia"</string>
@@ -187,7 +187,7 @@
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Eman fitxategi guztiak kudeatzeko baimena"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Eman multimedia-fitxategiak soilik erabiltzeko baimena"</string>
<string name="app_permission_button_allow_always" msgid="4573292371734011171">"Eman baimena beti"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Aplikazioa erabiltzean soilik"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Baimendu aplikazioa erabiltzean soilik"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Eman beti baliabide guztiak erabiltzeko baimena"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Galdetu beti"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Ez eman baimenik"</string>
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Erabili kokapen zehatza"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kokapen zehatza desaktibatuta dagoenean, aplikazioek gutxi gorabeherako kokapena atzi dezakete"</string>
<string name="app_permission_title" msgid="2090897901051370711">"\"<xliff:g id="PERM">%1$s</xliff:g>\" baimena"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Aplikazio honek <xliff:g id="PERM">%1$s</xliff:g> erabiltzeko duen baimena"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Aplikazio honek \"<xliff:g id="PERM">%1$s</xliff:g>\" erabiltzeko duen baimena"</string>
<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>
@@ -232,7 +232,7 @@
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Telefonoko deien erregistroa irakur dezakete baimen hau duten aplikazioek, baita bertan idatzi ere"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"Argazkiak atera eta bideoak graba ditzakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"Zure kontaktuak atzi ditzakete baimen hau duten aplikazioek"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Gailu honen kokapena atzi dezakete baimen hau duten aplikazioek"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Gailu honen kokapena erabil dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Inguruko gailuak aurkitu, haietara konektatu, eta haien arteko distantzia erlatiboa zehatz dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"Audioa graba dezakete baimen hau duten aplikazioek"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"Telefono-deiak egin eta kudea ditzakete baimen hau duten aplikazioek"</string>
@@ -251,7 +251,7 @@
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Multimedia-fitx. soilik erabiltzeko baimena dutenak"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Fitxategi guztiak kudeatzeko baimena dutenak"</string>
<string name="ask_header" msgid="2633816846459944376">"Galdetu beti"</string>
- <string name="denied_header" msgid="903209608358177654">"Baimendu gabe"</string>
+ <string name="denied_header" msgid="903209608358177654">"Baimendu gabekoak"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"Ikusi fitxategi guztiak atzi ditzaketen aplikazio gehiago"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 egun}other{# egun}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# ordu}other{# ordu}}"</string>
@@ -381,7 +381,7 @@
<string name="role_home_search_keywords" msgid="3830755001192666285">"abiarazlea"</string>
<string name="role_call_redirection_label" msgid="5785304207206147590">"Deiak desbideratzeko aplikazio lehenetsia"</string>
<string name="role_call_redirection_short_label" msgid="7568143419571217757">"Deiak birbideratzeko aplikazioa"</string>
- <string name="role_call_redirection_description" msgid="6091669882014664420">"Egiten dituzun deiak beste telefono-zenbaki batera desbideratzeko aukera ematen dizuten aplikazioak"</string>
+ <string name="role_call_redirection_description" msgid="6091669882014664420">"Irteerako deiak beste telefono-zenbaki batera desbideratzeko aukera ematen dizuten aplikazioak"</string>
<string name="role_call_redirection_request_title" msgid="2816244455003562925">"<xliff:g id="APP_NAME">%1$s</xliff:g> ezarri nahi duzu deiak birbideratzeko aplikazio lehenetsi gisa?"</string>
<string name="role_call_redirection_request_description" msgid="3118895714178527164">"Ez du behar baimenik"</string>
<string name="role_call_screening_label" msgid="883935222060878724">"Deitzailearen id. eta spam-aplikazio lehenetsia"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Erakutsi laguntzailea abiarazteko hautematea"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mikrofonoa erabiltzen denean ahozko laguntza aktibatzeko, erakutsi dagokion ikonoa egoera-barran"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Gailuko argazkiak eta multimedia-edukia erabiltzeko baimena eman nahi diozu &lt;b&amp;gt<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Kontaktuak erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Gailuaren kokapena erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Hura erabiltzen ari zarenean soilik atzituko du aplikazioak kokapena"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Gailuaren kokapena erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Baliteke aplikazioak beti atzitu behar izatea zure kokapena, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimen hori Ezarpenak atalean"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Kokapenerako sarbidea aldatu nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplikazioak beti atzitu nahi du zure kokapena, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimen hori Ezarpenak atalean"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Inguruko gailuak aurkitu, haietara konektatu eta haien arteko distantzia erlatiboa zehazteko baimena eman &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Inguruko gailuak aurkitzeko, haietara konektatzeko eta haien arteko distantzia erlatiboa zehazteko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt aplikazioari? "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> aplikazioak gutxi gorabeherako kokapena atzi dezake. Kokapen zehatza erabiltzeko baimena eman nahi diozu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Gailuaren gutxi gorabeherako kokapena erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Zehatza"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Gutxi gorabeherakoa"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Egutegia erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS mezuak bidaltzeko eta ikusteko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Gailuko argazkiak, multimedia-edukia eta fitxategiak erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Gailuko &lt;b&gt;argazkiak, bideoak, musika eta audioa&lt;/b&gt; erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Gailuko &lt;b&gt;argazkiak, bideoak, musika, audioa eta bestelako fitxategiak&lt;/b&gt; erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Gailuko musika eta audioa erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Gailuko argazkiak eta bideoak erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Gailuko argazki eta bideo gehiago erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Audioa grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikazioak hura erabiltzean soilik grabatuko du audioa"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Audioa grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Baliteke aplikazioak edonoiz grabatzea audioa, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Mikrofonorako sarbidea aldatu nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Aplikazioak edonoiz grabatu nahi du audioa, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Zure jarduera fisikoa erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Argazkiak ateratzeko eta bideoak grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikazioak hura erabiltzean soilik aterako ditu argazkiak, eta grabatuko bideoak"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Argazkiak atera eta bideoak grabatzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Baliteke aplikazioak edonoiz ateratzea argazkiak eta grabatzea bideoak, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Kamerarako sarbidea aldatu nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Aplikazioak edonoiz atera nahi ditu argazkiak eta grabatu bideoak, baita aplikazioa erabiltzen ari ez zarenean ere. "<annotation id="link">"Eman baimena ezarpenetan."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Telefonoko deien erregistroa erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Bizi-konstanteei buruzko sentsorearen datuak erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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 erabiltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Aplikazioari gorputz-sentsoreen datuak beti erabiltzeko baimena emateko (baita aplikazioa erabiltzen ari ez zarenean ere), "<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 erabiltzeko baimena eman nahi diozu aplikazio horri?"</string>
- <string name="permgrouprequest_notifications" msgid="6396739062335106181">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrolatutako baimenak"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Jakinarazpenak bidaltzeko baimena eman nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolatutako baimenak"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak kokapena erabil dezake"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Erakundeak kokapena erabiltzeko baimena eman dio <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioari"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Beste baimen batzuk"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Sistemak erabilitako baimenak"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Sistema-aplikazioek soilik erabilitako baimenak."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Agian hirugarrenekin kokapen-datuak partekatuko dituela adierazi du aplikazioaren garatzaileak"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datuak partekatzeko moduak eta kokapena"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Nondik dator datuak partekatzeko moduei buruzko informazioa?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Aplikazioak datuak partekatzeko dituen moduei buruzko informazioa eman dio gailuaren fabrikatzaileari garatzaileak. Baliteke garatzaileak informazio hori eguneratzea denboran zehar."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Aplikazioak datuak partekatzeko dituen moduei buruzko informazioa eman du "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" dendan garatzaileak. Baliteke garatzaileak informazio hori eguneratzea denboran zehar."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Baliteke hauetarako partekatzea kokapen-datuak:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datuak partekatzeko moduak aldatu egiten dira"</string>
@@ -608,9 +661,7 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datuen babesa"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Baliteke kokapen-datuak partekatzea"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Agian hirugarrenekin kokapen-datuak partekatuko dituela adierazi du aplikazioaren garatzaileak"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Ezin da ireki esteka"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
- <string name="data_sharing_updates_title" msgid="7996933386875213859">"Kokapen-datuak partekatzeko jardunbideen inguruko berritasunak"</string>
+ <string name="data_sharing_updates_title" msgid="7996933386875213859">"Kokapen-datuak partekatzeko jardunbideen berritasunak"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Berrikusi kokapen-datuak partekatzeko modua aldatu duten aplikazioak"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Kokapen-datuak partekatzeko modua aldatu dute aplikazio hauek. Agian ez zuten daturik partekatzen lehen, edo baliteke orain publizitate- edo marketin-helburuetarako partekatzea."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Datuak partekatzeko jardunbideei buruzko informazioa eman dute aplikazio-denda batean aplikazio hauen garatzaileek. Baliteke denboran zehar informazio hori eguneratzea.\n\nLitekeena da datuak partekatzeko jardunbideak aplikazioaren bertsioaren, erabileraren, lurraldearen eta adinaren araberakoak izatea."</string>
diff --git a/PermissionController/res/values-fa-v33/strings.xml b/PermissionController/res/values-fa-v33/strings.xml
index b46c08f50..6c7abf7c5 100644
--- a/PermissionController/res/values-fa-v33/strings.xml
+++ b/PermissionController/res/values-fa-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"هشدارهای بیشتر"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"هشدارهای ردشده"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{گسترده کردن و دیدن یک هشدار دیگر}one{گسترده کردن و دیدن # هشدار دیگر}other{گسترده کردن و دیدن # هشدار دیگر}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"هشدار. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"کنش کامل شد"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"بررسی کردن تنظیماتی که می‌تواند امنیت بیشتری به دستگاهتان اضافه کند"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"تنظیمات فوری امنیت و حریم خصوصی"</string>
diff --git a/PermissionController/res/values-fa/strings.xml b/PermissionController/res/values-fa/strings.xml
index 7be621a55..cb7b1454e 100644
--- a/PermissionController/res/values-fa/strings.xml
+++ b/PermissionController/res/values-fa/strings.xml
@@ -32,16 +32,16 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"تغییر ندادن اجازه «هنگامی که از برنامه استفاده می‌شود»"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"«فقط این بار» نگه داشته شود"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"اطلاعات بیشتر"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"همه مجازاند"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"مجاز بودن همه"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"همه موارد همیشه مجازاند"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"انتخاب عکس و ویدیو"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"انتخاب موارد بیشتر"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"موارد بیشتری انتخاب نشود"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"دیگر چیزی انتخاب نشود"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"درهرصورت اجازه نیست"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"رد کردن"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> مجوز از <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> مجوز"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه <xliff:g id="ACTION">%2$s</xliff:g> را می‌دهید؟"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"‏همیشه به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; برای <xliff:g id="ACTION">%2$s</xliff:g> اجازه داده شود؟"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; این اجازه داده شود؟ <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"‏همیشه به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; این اجازه داده شود؟ <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"فقط هنگام استفاده از برنامه"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"همیشه"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"اجازه نیست و دیگر پرسیده نشود"</string>
@@ -113,7 +113,7 @@
<string name="loading" msgid="4789365003890741082">"درحال بارگیری…"</string>
<string name="all_permissions" msgid="6911125611996872522">"همه مجوزها"</string>
<string name="other_permissions" msgid="2901186127193849594">"سایر قابلیت‌های برنامه"</string>
- <string name="permission_request_title" msgid="8790310151025020126">"درخواست مجوز"</string>
+ <string name="permission_request_title" msgid="8790310151025020126">"درخواست اجازه"</string>
<string name="wear_not_allowed_dlg_title" msgid="1429467891296932713">"Android Wear"</string>
<string name="wear_not_allowed_dlg_text" msgid="512340555334769098">"‏کنش‌های نصب/حذف نصب در Wear پشتیبانی نمی‌شود."</string>
<string name="permission_review_title_template_install" msgid="1284337937156289081">"‏انتخاب کنید &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه دارد به چه چیزی دسترسی پیدا کند"</string>
@@ -203,7 +203,7 @@
<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_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>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"آخرین باری که باز شده: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"اگر مدیریت همه فایل‌ها را مجاز کنید، این برنامه می‌تواند به همه فایل‌های موجود در فضای ذخیره‌سازی استاندارد این دستگاه یا دستگاه‌های ذخیره‌سازی متصل دسترسی داشته باشد، آن‌ها را تغییر دهد، و حذف کند. این برنامه ممکن است بدون سؤال کردن از شما به فایل‌ها دسترسی پیدا کند."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"به این برنامه اجازه داده شود به فایل‌های موجود در این دستگاه یا دستگاه‌های ذخیره‌سازی متصل دسترسی داشته باشد، آن‌ها را تغییر دهد، و حذف کند؟ این برنامه ممکن است بدون سؤال کردن از شما به فایل‌ها دسترسی پیدا کند."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"برنامه‌هایی که این مجوز را داشته باشند مجاز هستند به: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"برنامه‌هایی که این اجازه را داشته باشند برای این هم مجازند: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"برنامه‌های دارای این اجازه می‌توانند به فعالیت فیزیکی‌تان مانند پیاده‌روی، دوچرخه‌سواری، رانندگی، قدم‌شماری، و غیره دسترسی داشته باشند"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"برنامه‌های دارای این اجازه می‌توانند به تقویمتان دسترسی داشته باشند"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"برنامه‌هایی که این مجوز را داشته باشند می‌توانند گزارش تماس تلقنی را بخوانند و بنویسند"</string>
@@ -246,12 +246,12 @@
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"هرگز دسترسی نداشته است"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"غیرمجاز / هرگز دسترسی نداشته است"</string>
<string name="allowed_header" msgid="7769277978004790414">"مجاز است"</string>
- <string name="allowed_always_header" msgid="6455903312589013545">"همیشه مجاز است"</string>
- <string name="allowed_foreground_header" msgid="6845655788447833353">"مجاز فقط هنگام استفاده از برنامه"</string>
+ <string name="allowed_always_header" msgid="6455903312589013545">"همیشه مجاز بودن"</string>
+ <string name="allowed_foreground_header" msgid="6845655788447833353">"مجاز فقط هنگام استفاده"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"مجاز فقط برای دسترسی به رسانه‌ها"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"مجاز برای مدیریت همه فایل‌ها"</string>
<string name="ask_header" msgid="2633816846459944376">"هربار پرسیده شود"</string>
- <string name="denied_header" msgid="903209608358177654">"اجازه ندادن"</string>
+ <string name="denied_header" msgid="903209608358177654">"مجاز نبودن"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"دیدن برنامه‌های دیگری که به همه فایل‌ها دسترسی دارند"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{یک روز}one{# روز}other{# روز}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# ساعت}one{# ساعت}other{# ساعت}}"</string>
@@ -314,7 +314,7 @@
<string name="permission_subtitle_only_in_foreground" msgid="9068389431267377564">"تنها هنگام استفاده از برنامه"</string>
<string name="permission_subtitle_media_only" msgid="8917869683764720717">"رسانه"</string>
<string name="permission_subtitle_all_files" msgid="4982613338298067862">"همه فایل‌ها"</string>
- <string name="permission_subtitle_background" msgid="8916750995309083180">"همیشه مجاز است"</string>
+ <string name="permission_subtitle_background" msgid="8916750995309083180">"همیشه مجاز بودن"</string>
<string name="app_perms_24h_access" msgid="99069906850627181">"آخرین زمان دسترسی: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_perms_24h_access_yest" msgid="5411926024794555022">"آخرین زمان دسترسی دیروز ساعت <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_perms_7d_access" msgid="4945055548894683751">"آخرین دسترسی: <xliff:g id="TIME_DATE_0">%1$s</xliff:g> ساعت <xliff:g id="TIME_DATE_1">%2$s</xliff:g>"</string>
@@ -405,8 +405,8 @@
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"دوباره سؤال نشود"</string>
<string name="request_role_set_as_default" msgid="4253949643984172880">"تنظیم برای پیش‌فرض"</string>
<string name="phone_call_uses_microphone" msgid="233569591461187177">"‏در &lt;b&gt;تماس تلفنی&lt;/b&gt; از میکروفون استفاده می‌شود"</string>
- <string name="phone_call_uses_microphone_and_camera" msgid="6291898755681748189">"‏در &lt;b&gt;تماس ویدیویی&lt;/b&gt; از دوربین و میکروفون استفاده می‌شود"</string>
- <string name="phone_call_uses_camera" msgid="2048417022147857418">"‏در &lt;b&gt;تماس ویدیویی&lt;/b&gt; از دوربین استفاده می‌شود"</string>
+ <string name="phone_call_uses_microphone_and_camera" msgid="6291898755681748189">"‏در &lt;b&gt;تماس تصویری&lt;/b&gt; از دوربین و میکروفون استفاده می‌شود"</string>
+ <string name="phone_call_uses_camera" msgid="2048417022147857418">"‏در &lt;b&gt;تماس تصویری&lt;/b&gt; از دوربین استفاده می‌شود"</string>
<string name="system_uses_microphone" msgid="576672130318877143">"سرویس سیستم به میکروفون دسترسی دارد"</string>
<string name="system_uses_microphone_and_camera" msgid="5124478304275138804">"سرویس سیستم به دوربین و میکروفون دسترسی دارد"</string>
<string name="system_uses_camera" msgid="1911223105234441470">"سرویس سیستم به دوربین دسترسی دارد"</string>
@@ -455,53 +455,78 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"نمایش دستیار تشخیص راه‌انداز"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"نمایش نماد مربوطه در نوار وضعیت وقتی از میکروفون برای فعال کردن دستیار صوتی استفاده می‌شود"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; اجازه داده شود به عکس‌ها و رسانه‌های موجود در دستگاهتان دسترسی پیدا کند؟"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به عکس‌ها و رسانه‌های &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مخاطبین شما دسترسی پیدا کند؟"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مخاطبینتان در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مکان این دستگاه دسترسی پیدا کند؟"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مکان &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"این برنامه فقط وقتی از آن استفاده می‌کنید، به مکان دسترسی خواهد داشت"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مکان این دستگاه دسترسی پیدا کند؟"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مکان &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g> دسترسی داشته باشد؟"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"این برنامه ممکن است بخواهد مرتب به مکانتان دسترسی داشته باشد، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"‏دسترسی به مکان برای &lt;b&amp;gt؛<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt تغییر کند؟"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"‏دسترسی &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; به مکان در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"این برنامه می‌خواهد مرتب به مکانتان دسترسی داشته باشد، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود دستگاه‌های اطراف را پیدا کند، به آن‌ها متصل شود، و موقعیت نسبی آن‌ها را مشخص کند؟"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دستگاه‌های اطراف را پیدا کند، به آن‌ها متصل شود، و موقعیت نسبی آن‌ها را تعیین کند؟"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود دستگاه‌های اطراف را پیدا کند، به آن‌ها متصل شود، و موقعیت نسبی آن‌ها را مشخص کند؟ "<annotation id="link">"در تنظیمات اجازه دهید."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"دسترسی <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> به مکان از حالت تقریبی به دقیق تغییر کند؟"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"‏دسترسی <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> به مکان &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; از تقریبی به دقیق تغییر کند؟"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"‏به &lt;b&amp;gt؛<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt؛ اجازه داده شود به مکان تقریبی این دستگاه دسترسی پیدا کند؟"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به مکان تقریبی &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"دقیق"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"تقریبی"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه دسترسی به تقویمتان داده شود؟"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به تقویمتان در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"‏به «&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt;» اجازه داده شود پیامک ارسال و مشاهده کند؟"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; پیامک ارسال کند و پیامک‌ها را مشاهده کند؟"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‏به برنامه &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; اجازه داده شود به عکس‌ها، رسانه، و فایل‌های موجود در دستگاهتان دسترسی داشته باشد؟"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به عکس‌ها، رسانه‌ها، و فایل‌های &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به &lt;b&gt;عکس‌ها، ویدیوها، موسیقی، و فایل‌های صوتی&lt;/b&gt; این دستگاه دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به &lt;b&gt;عکس‌ها، ویدیوها، موسیقی، صوت، و فایل‌های دیگر&lt;/b&gt; این دستگاه دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به فایل‌های موسیقی و صوتی در این دستگاه دسترسی داشته باشد؟"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; به فایل‌های موسیقی و صوتی دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به عکس‌ها و ویدیوهای این دستگاه دسترسی داشته باشد؟"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به عکس‌ها و ویدیوهای &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به عکس‌ها و ویدیوهای بیشتری در این دستگاه دسترسی داشته باشد؟"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به عکس‌ها و ویدیوهای بیشتری در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏به &lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود صدا ضبط کند؟"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; صدا ضبط کند؟"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"این برنامه فقط وقتی از آن استفاده می‌کنید، می‌تواند صدا ضبط کند"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏به &lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود صدا ضبط کند؟"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; صدا ضبط کند؟"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"این برنامه ممکن است بخواهد مرتب صدا ضبط کند، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‏دسترسی به میکروفون برای &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"‏دسترسی &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; به میکروفون در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"این برنامه می‌خواهد مرتب صدا ضبط کند، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید به فعالیت فیزیکی‌تان دسترسی پیدا کند؟"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به فعالیت فیزیکی‌تان در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود عکس بگیرد و ویدیو ضبط کند؟"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; t اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; عکس بگیرد و ویدیو ضبط کند؟"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"این برنامه فقط وقتی از آن استفاده می‌کنید، می‌تواند عکس و فیلم بگیرد"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود عکس بگیرد و ویدیو ضبط کند؟"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; t اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; عکس بگیرد و ویدیو ضبط کند؟"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"این برنامه ممکن است بخواهد مرتب عکس و فیلم بگیرد، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"‏دسترسی به دوربین برای &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"‏دسترسی &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; به دوربین در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; تغییر کند؟"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"این برنامه می‌خواهد مرتب عکس و فیلم بگیرد، حتی زمانی‌که از برنامه استفاده نمی‌کنید. "<annotation id="link">"در تنظیمات به آن اجازه دهید."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به گزارش‌های تماس تلفنتان در &lt;b&gt;<xliff:g id="DEVICE">%2$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_device_aware_phone" msgid="4389610977195521813">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به داده‌های علائم حیاتی‌تان از حسگر &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود به داده‌های علائم حیاتی‌تان از حسگر &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; دسترسی داشته باشد؟"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"برای اینکه این برنامه بتواند همیشه و حتی زمانی که از برنامه استفاده نمی‌کنید به داده‌های حسگر بدن دسترسی داشته باشد، "<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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; همچنان اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود در &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; اعلان ارسال کند؟"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"مجوزهای کنترل‌شده"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
- <skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
- <skip />
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> به مکان دسترسی دارد"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"سازمان شما به <xliff:g id="APP_NAME">%1$s</xliff:g> اجازه داده است به مکانتان دسترسی داشته باشد"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"اجازه‌های دیگر"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"اجازه‌هایی که سیستم استفاده می‌کند"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"اجازه‌هایی که فقط برنامه‌های سیستم استفاده می‌کنند."</string>
@@ -591,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"این برنامه اعلام کرده است که ممکن است داده‌های مکان را با اشخاص ثالث هم‌رسانی کند"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"هم‌رسانی داده‌ها و مکان"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"اطلاعات هم‌رسانی داده از کجا می‌آید"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"توسعه‌دهنده اطلاعاتی درباره نحوه هم‌رسانی داده‌ها توسط این برنامه به سازنده این دستگاه ارائه کرده است. ممکن است توسعه‌دهنده این اطلاعات را به‌مرور زمان به‌روز کند."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"‏توسعه‌دهنده در "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" اطلاعاتی درباره نحوه هم‌رسانی داده‌ها توسط این برنامه ارائه کرده است. ممکن است توسعه‌دهنده این اطلاعات را به‌مرور زمان به‌روز کند."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"برنامه شاید داده‌های مکان را به این دلایل هم‌رسانی کند:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"روش‌های هم‌رسانی داده متفاوت است"</string>
@@ -608,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ایمنی داده"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"داده‌های مکان ممکن است هم‌رسانی شود"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"این برنامه اعلام کرده که ممکن است داده‌های مکانتان را با اشخاص ثالث هم‌رسانی کند"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"این پیوند باز نشد"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"به‌روزرسانی‌های هم‌رسانی داده برای مکان"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"برنامه‌هایی که روش هم‌رسانی داده‌های مکان شما را تغییر داده‌اند مرور کنید"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"این برنامه‌ها روش هم‌رسانی داده‌های مکان شما را تغییر داده‌اند. شاید قبلاً آن را هم‌رسانی نکرده باشند، یا شاید اکنون آن را برای اهداف تبلیغاتی یا بازاریابی هم‌رسانی کنند."</string>
diff --git a/PermissionController/res/values-fi-v33/strings.xml b/PermissionController/res/values-fi-v33/strings.xml
index 32e3cabe8..9b57c6172 100644
--- a/PermissionController/res/values-fi-v33/strings.xml
+++ b/PermissionController/res/values-fi-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Lisää ilmoituksia"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Hylätyt hälytykset"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Laajenna ja katso yksi muu ilmoitus}other{Laajenna ja katso # muuta ilmoitusta}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Hälytys. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Toiminto suoritettu"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Tarkista asetukset, jotka voivat parantaa laitteesi turvallisuutta"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Tietosuojan ja yksityisyyden pika-asetukset"</string>
diff --git a/PermissionController/res/values-fi-v34/strings.xml b/PermissionController/res/values-fi-v34/strings.xml
index bd264d879..b2f95dc19 100644
--- a/PermissionController/res/values-fi-v34/strings.xml
+++ b/PermissionController/res/values-fi-v34/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="security_privacy_brand_name" msgid="7303621734258440812">"Tietoturva ja yksityisyys"</string>
+ <string name="security_privacy_brand_name" msgid="7303621734258440812">"Turvallisuus ja yksityisyys"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Asetukset"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"Päätä sovellusten pääsystä terveysdataan"</string>
diff --git a/PermissionController/res/values-fi/strings.xml b/PermissionController/res/values-fi/strings.xml
index 6bfe39862..e9b97ce27 100644
--- a/PermissionController/res/values-fi/strings.xml
+++ b/PermissionController/res/values-fi/strings.xml
@@ -40,7 +40,7 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Älä salli silti"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Ohita"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Sallitaanko toiminto <xliff:g id="ACTION">%2$s</xliff:g> sovellukselle &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aina <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aina <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Vain sovelluksen käytön aikana"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Aina"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Salli aina"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Salli vain, kun sov. on käyt."</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Salli vain, kun sovellus käytössä"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Älä salli"</string>
<string name="loading" msgid="4789365003890741082">"Ladataan…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Kaikki luvat"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Näytä avustajan käynnistyskomennon havaitseminen"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Näytä tilarivillä kuvake, kun ääniapuri aktivoidaan mikrofonin avulla."</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää laitteellasi olevia kuvia ja mediaa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; yhteystietojesi käyttöoikeuden?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn tämän laitteen sijaintiin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Sovellus saa sijainnin käyttöoikeuden vain silloin, kun käytät sovellusta"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn tämän laitteen sijaintiin?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Sovellus voi haluta nähdä sijaintisi aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Muutetaanko sijainnin käyttöoikeutta (&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;)?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Sovellus haluaa nähdä sijaintisi aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; löytää lähellä olevia laitteita, yhdistää niihin ja määrittää niiden suhteellisen sijainnin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; löytää lähellä olevia laitteita, yhdistää niihin ja määrittää niiden suhteellisen sijainnin? "<annotation id="link">"Myönnä lupa asetuksista."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Muutetaanko sijainnin käyttöoikeus (<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>) likimääräisestä tarkaksi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn tämän laitteen karkeaan sijaintiin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Tarkka"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Likimääräinen"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn kalenteriisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; lähettää ja lukea tekstiviestejä?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; käyttää laitteellasi olevia kuvia, mediaa ja tiedostoja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn laitteen &lt;b&gt;kuviin, videoihin, musiikkiin ja audioon&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn &lt;b&gt;kuviin, videoihin, musiikkiin, audioon ja muihin tiedostoihin&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn tällä laitteella oleviin musiikki- ja audiotiedostoihin?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn laitteella oleviin kuviin ja mediaan?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pääsyn useampiin laitteella oleviin kuviin ja mediaan?"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nauhoittaa audiota?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tallentaa audiota?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Sovellus voi tallentaa audiota vain silloin, kun käytät sitä"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tallentaa audiota?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Sovellus voi haluta tallentaa audiota aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Muutetaanko mikrofonin käyttöoikeutta (&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;)?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Sovellus haluaa tallentaa audiota aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nähdä liikkumistietosi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ottaa kuvia ja nauhoittaa videoita?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Sovellus voi ottaa kuvia ja videoita vain silloin, kun käytät sitä"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ottaa kuvia ja videoita?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Sovellus voi haluta ottaa kuvia ja videoita aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Muutetaanko kameran käyttöoikeutta (&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;)?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Sovellus haluaa ottaa kuvia ja videoita aina, myös silloin kun et käytä sitä. "<annotation id="link">"Myönnä lupa asetuksista"</annotation>"."</string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Jos haluat myöntää sovellukselle pääsyn kehoanturidataan aina, myös silloin, kun et käytä sovellusta, "<annotation id="link">"siirry 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="auto_granted_permissions" msgid="6009452264824455892">"Automaattisesti myönnetyt käyttöoikeudet"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Automaattisesti myönnetyt käyttöoikeudet"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Sovelluksella (<xliff:g id="APP_NAME">%1$s</xliff:g>) on pääsy sijaintiin"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organisaatiosi sallii sovelluksen (<xliff:g id="APP_NAME">%1$s</xliff:g>) pääsyn sijaintiin"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Muut luvat"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Järjestelmän käyttämät luvat"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Vain järjestelmäsovellusten käyttämät luvat"</string>
@@ -522,7 +574,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Sovellusten ja palvelujen osalta"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Mikrofonidataa saatetaan silti jakaa, kun soitat hätänumeroon."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Muuta"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Tietoturva ja yksityisyys"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Turvallisuus ja yksityisyys"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"Tarkista laite"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Ohita"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Ohitetaanko tämä hälytys?"</string>
@@ -533,7 +585,7 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"Tietoturvan ja yksityisyyden tila. <xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>. <xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"Turvallisuusasetukset"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Luvat"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Tietoturva ja yksityisyys"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Turvallisuus ja yksityisyys"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Tarkista tila"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Yksityisyysasetukset"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Lisää asetuksia"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Sovellus on ilmoittanut, että se saattaa jakaa sijaintitietoja kolmansille osapuolille"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datan jakaminen ja sijainti"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Mistä datan jakotiedot tulevat"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Kehittäjä on antanut laitteen valmistajalle tietoja tavoista, joilla sovellus jakaa dataa. Kehittäjä voi päivittää tietoja ajan mittaan."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883"><annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sisältää kehittäjän lisäämiä tietoja tavoista, joilla sovellus jakaa dataa. Kehittäjä voi päivittää tietoja ajan mittaan."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Sijaintitietoja voidaan jakaa näihin tarkoituksiin"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datan jakaminen vaihtelee"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Dataturvallisuus"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Sijaintitietoja voidaan jakaa"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Sovellus on ilmoittanut, että se saattaa jakaa sijaintitietoja kolmansille osapuolille"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Linkki ei avaudu"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Sijaintidatan jakamisen päivitykset"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Tarkista sovellukset, jotka ovat muuttaneet tapaa, jolla ne voivat jakaa sijaintitietoja"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Nämä sovellukset ovat muuttaneet tapaa, jolla ne voivat jakaa sijaintitietoja. Ne eivät ehkä ole jakaneet niitä aiemmin tai ne saattavat nyt jakaa niitä mainonta- tai markkinointitarkoituksiin."</string>
diff --git a/PermissionController/res/values-fr-rCA-v33/strings.xml b/PermissionController/res/values-fr-rCA-v33/strings.xml
index 722d0c2dc..808e1bcd9 100644
--- a/PermissionController/res/values-fr-rCA-v33/strings.xml
+++ b/PermissionController/res/values-fr-rCA-v33/strings.xml
@@ -19,7 +19,7 @@
<string name="role_dialer_request_description" msgid="6188305064871543419">"Cette application sera autorisée à vous envoyer des notifications; elle aura accès à votre appareil photo, à vos contacts, à votre microphone, à votre téléphone et à vos messages texte"</string>
<string name="role_sms_request_description" msgid="1506966389698625395">"Cette application sera autorisée à vous envoyer des notifications; elle aura accès à votre appareil photo, à vos contacts, à vos fichiers, à votre microphone, à votre téléphone et à vos messages texte"</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"Les applications possédant cette autorisation peuvent accéder à tous les fichiers sur cet appareil"</string>
- <string name="work_policy_title" msgid="832967780713677409">"Les détails de votre politique professionnelle"</string>
+ <string name="work_policy_title" msgid="832967780713677409">"Infos sur votre politique de travail"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"Les paramètres sont gérés par votre administrateur informatique"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Développer et afficher la liste"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"Réduire la liste et masquer les paramètres"</string>
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Plus d\'alertes"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertes ignorées"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Développez et affichez une autre alerte}one{Développez et affichez # autre alerte}many{Développez et affichez # d\'autres alertes}other{Développez et affichez # autres alertes}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerte. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Action terminée"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Vérifiez les paramètres qui peuvent protéger davantage votre appareil"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Paramètres rapides de sécurité et de confidentialité"</string>
diff --git a/PermissionController/res/values-fr-rCA-v34/strings.xml b/PermissionController/res/values-fr-rCA-v34/strings.xml
index ab03d9ca2..347b04cc8 100644
--- a/PermissionController/res/values-fr-rCA-v34/strings.xml
+++ b/PermissionController/res/values-fr-rCA-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Sécurité et confidentialité"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Commandes"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Connexion santé"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Gérer l\'accès des applications aux données relatives à la santé"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Gérez l\'accès des applications aux données relatives à la santé"</string>
<string name="location_settings" msgid="8863940440881290182">"Accès à la position"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Pour les applications et les services. Si ce paramètre est désactivé, il est possible que les données du microphone soient partagées lorsque vous appelez un numéro d\'urgence"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Pour les applications et les services"</string>
diff --git a/PermissionController/res/values-fr-rCA/strings.xml b/PermissionController/res/values-fr-rCA/strings.xml
index 0c2615b83..81a97afba 100644
--- a/PermissionController/res/values-fr-rCA/strings.xml
+++ b/PermissionController/res/values-fr-rCA/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Toujours tout autoriser"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Sélectionner des photos et des vidéos"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Sélectionner d\'autres photos"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ne pas sélectionner plus de données"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ne pas en sélectionner d\'autres"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ne pas autoriser quand même"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Fermer"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> sur <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Dernière ouverture : <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Si vous autorisez la gestion de tous les fichiers, cette application pourra accéder à tous les fichiers enregistrés dans l\'espace de stockage partagé sur cet appareil ou sur des appareils de stockage connectés, les modifier et les supprimer. L\'application pourra accéder à des fichiers sans vous demander la permission."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Autoriser cette application à accéder aux fichiers qui se trouvent sur cet appareil ou sur des appareils de stockage connectés et à les modifier et les supprimer. Cette application pourra accéder à des fichiers sans vous demander la permission."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Les applications qui possèdent l\'autorisation peuvent <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Les applications ayant cette autorisation peuvent <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Les applications qui possèdent cette autorisation peuvent accéder aux données relatives à vos activités physiques, comme la marche, le vélo, la conduite, le nombre de pas effectués et plus encore"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Les applications qui possèdent cette autorisation peuvent accéder à votre agenda"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Les applications qui possèdent cette autorisation peuvent lire et écrire des journaux d\'appels téléphoniques"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Afficher la détection des déclencheurs de l\'assistant"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Afficher l\'icône dans la barre d\'état lorsque le microphone est utilisé pour activer l\'assistant vocal"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Autoriser <xliff:g id="APP_NAME">%1$s</xliff:g> à accéder aux photos et aux médias de votre appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à vos contacts?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position de cet appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"L\'application aura uniquement accès à la position lorsque vous l\'utilisez"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position de cet appareil?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Cette appli pourrait demander à accéder à votre position en tout temps, même si vous ne l\'utilisez pas. Accordez cette autorisation dans les "<annotation id="link">"paramètres"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Modifier l\'accès à la position pour « <xliff:g id="APP_NAME">%1$s</xliff:g> »?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Cette application veut accéder à votre position en tout temps, même lorsque vous ne l\'utilisez pas. Accordez cette autorisation dans les "<annotation id="link">"paramètres"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à trouver les appareils à proximité, à s\'y connecter et à déterminer leur position relative?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à trouver les appareils à proximité, à s\'y connecter et à déterminer leur position relative? "<annotation id="link">"Accordez l\'autorisation dans les paramètres."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Modifier l\'accès à la position de l\'application <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> d\'approximative à exacte?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position approximative de cet appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exacte"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximative"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à votre agenda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à envoyer et à afficher des messages texte?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos, au contenu multimédia et aux fichiers de votre appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder &lt;b&gt;aux photos, aux vidéos, et aux fichiers musicaux et audio&lt;/b&gt; sur cet appareil?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder &lt;b&gt;aux photos, aux vidéos, et aux fichiers musicaux, audio et autres&lt;/b&gt; sur cet appareil?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux fichiers musicaux et audio sur cet appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos et aux vidéos sur cet appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à plus de photos et de vidéos sur cet appareil?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à enregistrer l\'audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"L\'application pourra uniquement enregistrer de l\'audio lorsque vous l\'utilisez"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à enregistrer de l\'audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Cette application pourrait demander à enregistrer de l\'audio en tout temps, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez dans les paramètres."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Modifier l\'accès au microphone pour « <xliff:g id="APP_NAME">%1$s</xliff:g> »?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Cette application veut enregistrer de l\'audio en tout temps, même si vous ne l\'utilisez pas. "<annotation id="link">"Autorisez dans les paramètres."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder à vos activités physiques?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à prendre des photos et à enregistrer des vidéos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"L\'application pourra uniquement prendre des photos et enregistrer des vidéos lorsque vous l\'utilisez"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à prendre des photos et à enregistrer des vidéos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Cette appli pourrait demander à prendre des photos et des vidéos en tout temps, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez dans les paramètres."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Modifier l\'accès à l\'appareil photo pour « <xliff:g id="APP_NAME">%1$s</xliff:g> »?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Cette application veut prendre des photos et enregistrer des vidéos en tout temps, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez dans les paramètres."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Cette application souhaite pouvoir accéder en tout temps aux données des 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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à vous envoyer des notifications?"</string>
- <string name="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> dispose d\'un accès à la position"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Votre organisation permet à <xliff:g id="APP_NAME">%1$s</xliff:g> d\'accéder à votre position"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Autres autorisations"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Autorisations utilisées par le système"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Autorisations utilisées par les applications système."</string>
@@ -537,7 +589,7 @@
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Vérification de l\'état"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Paramètres de confidentialité"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Plus de paramètres"</string>
- <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Accès à l\'appareil photo"</string>
+ <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Accès à la caméra"</string>
<string name="microphone_toggle_label_qs" msgid="8132912469813396552">"Accès au microphone"</string>
<string name="permissions_removed_qs" msgid="8957319130625294572">"L\'autorisation a été retirée"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"Consulter les utilisations récentes de l\'appareil photo"</string>
@@ -579,18 +631,19 @@
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Accès modifié"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Voir les utilisations récentes de la position"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Paramètres de confidentialité"</string>
- <string name="camera_toggle_title" msgid="1251201397431837666">"Accès à l\'appareil photo"</string>
+ <string name="camera_toggle_title" msgid="1251201397431837666">"Accès à la caméra"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Accès au microphone"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Pour les applications et les services"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Pour les applications et les services. Si ce paramètre est désactivé, il est possible que les données du microphone soient partagées lorsque vous appelez un numéro d\'urgence."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Voir les applications et les services qui ont accès à votre emplacement"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Afficher l\'accès au presse-papiers"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Afficher un message lorsque les applications accèdent à du texte, à des images ou à d\'autres contenus que vous avez copiés"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Un message s\'affiche lorsque les applications accèdent à du texte, à des images ou à d\'autres contenus que vous avez copiés"</string>
<string name="show_password_title" msgid="2877269286984684659">"Afficher les mots de passe"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Afficher les caractères brièvement pendant la saisie"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Les caractères s\'affichent brièvement pendant la saisie"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Cette application indique qu\'elle peut partager des données de localisation avec des tiers"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Partage des données et localisation"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Provenance des renseignements sur le partage des données"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Le développeur a fourni des renseignements au fabricant de cet appareil sur la façon dont cette application partage les données. Le développeur peut mettre à jour ces renseignements au fil du temps."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Le développeur a fourni des renseignements à "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sur la façon dont cette application partage les données. Le développeur peut mettre à jour ces renseignements au fil du temps."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"L\'appli peut partager des données de loc. pour :"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Les pratiques de partage de données peuvent varier"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Sécurité des données"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Les données de localisation peuvent être partagées"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Cette application indique qu\'elle peut partager vos données de localisation avec des tiers"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Impossible d\'ouvrir ce lien"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Mises à jour des pratiques de partage des données pour la localisation"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Passez en revue les applications qui ont changé la façon dont elles peuvent partager vos données de localisation"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ces applications ont modifié la façon dont elles peuvent partager vos données de localisation. Elles peuvent ne pas les avoir partagées auparavant, ou peuvent maintenant les partager à des fins d\'annonces ou de marketing."</string>
diff --git a/PermissionController/res/values-fr-v33/strings.xml b/PermissionController/res/values-fr-v33/strings.xml
index 1cb802ff5..24bd671a8 100644
--- a/PermissionController/res/values-fr-v33/strings.xml
+++ b/PermissionController/res/values-fr-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Autres alertes"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertes ignorées"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Développer et voir 1 autre alerte}one{Développer et voir # autre alerte}many{Développer et voir # autres alertes}other{Développer et voir # autres alertes}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerte. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Action terminée"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Vérifiez les paramètres qui peuvent renforcer la protection de votre appareil"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Réglages rapides de sécurité et de confidentialité"</string>
diff --git a/PermissionController/res/values-fr-v34/strings.xml b/PermissionController/res/values-fr-v34/strings.xml
index 59da70170..f7f584b75 100644
--- a/PermissionController/res/values-fr-v34/strings.xml
+++ b/PermissionController/res/values-fr-v34/strings.xml
@@ -22,6 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Santé Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"Gérer l\'accès de l\'appli aux données de santé"</string>
<string name="location_settings" msgid="8863940440881290182">"Accès à la position"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Pour les applis et services. Si ce paramètre est désactivé, il est possible que les données du micro soient quand même partagées quand vous appelez un numéro d\'urgence."</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Pour les applis et services. Si ce paramètre est désactivé, il est possible que les données du micro soient quand même partagées quand vous appelez un numéro d\'urgence"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Pour les applis et services"</string>
</resources>
diff --git a/PermissionController/res/values-fr/strings.xml b/PermissionController/res/values-fr/strings.xml
index 8e8215e72..cafe4c3af 100644
--- a/PermissionController/res/values-fr/strings.xml
+++ b/PermissionController/res/values-fr/strings.xml
@@ -81,7 +81,7 @@
<string name="storage_supergroup_warning_allow" msgid="103093462784523190">"Cette appli a été conçue pour une ancienne version d\'Android. Si vous lui accordez cette autorisation, elle aura accès à tout le contenu stocké (y compris, les photos, vidéos, fichiers musicaux et audio, et autres)."</string>
<string name="storage_supergroup_warning_deny" msgid="6420765672683284347">"Cette appli a été conçue pour une ancienne version d\'Android. Si vous lui refusez cette autorisation, elle n\'aura pas accès à l\'ensemble du contenu stocké (y compris, les photos, vidéos, fichiers musicaux et audio, et autres)."</string>
<string name="default_permission_description" msgid="4624464917726285203">"effectuer une action inconnue"</string>
- <string name="app_permissions_group_summary" msgid="8788419008958284002">"<xliff:g id="COUNT_0">%1$d</xliff:g> application(s) autorisée(s) sur <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
+ <string name="app_permissions_group_summary" msgid="8788419008958284002">"<xliff:g id="COUNT_0">%1$d</xliff:g> appli(s) autorisée(s) sur <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> applications autorisées"</string>
<string name="menu_show_system" msgid="4254021607027872504">"Voir applis système"</string>
<string name="menu_hide_system" msgid="3855390843744028465">"Masquer applis système"</string>
@@ -161,8 +161,8 @@
<string name="permission_usage_bar_chart_title_last_hour" msgid="6571647509660009185">"Autorisations utilisées (dernière heure)"</string>
<string name="permission_usage_bar_chart_title_last_15_minutes" msgid="2743143675412824819">"Autorisations utilisées (15 dernières minutes)"</string>
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Autorisations utilisées (dernière minute)"</string>
- <string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{Non utilisée au cours du dernier jour (#)}one{Non utilisée au cours du dernier jour (#)}many{Non utilisée au cours des # derniers jours}other{Non utilisée au cours des # derniers jours}}"</string>
- <string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{Non utilisée au cours de la dernière heure (#)}one{Non utilisée au cours de la dernière heure (#)}many{Non utilisée au cours des # dernières heures}other{Non utilisée au cours des # dernières heures}}"</string>
+ <string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{Pas d\'utilisation sur le dernier jour (#)}one{Pas d\'utilisation sur le dernier jour (#)}many{Pas d\'utilisation sur les # derniers jours}other{Pas d\'utilisation sur les # derniers jours}}"</string>
+ <string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{Pas d\'utilisation sur la dernière heure (#)}one{Pas d\'utilisation sur la dernière heure (#)}many{Pas d\'utilisation sur les # dernières heures}other{Pas d\'utilisation sur les # dernières heures}}"</string>
<string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{Utilisation par 1 appli}one{Utilisation par # appli}many{Utilisation par # applis}other{Utilisation par # applis}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Tout afficher dans le tableau de bord"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Données filtrées par : <xliff:g id="PERM">%1$s</xliff:g>"</string>
@@ -187,7 +187,7 @@
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Autoriser la gestion de tous les fichiers"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Autoriser l\'accès aux fichiers multimédias uniquement"</string>
<string name="app_permission_button_allow_always" msgid="4573292371734011171">"Toujours autoriser"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Autoriser seulement si l\'appli est en cours d\'utilisation"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"Autoriser seulement si l\'appli est utilisée"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Toujours autoriser"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Toujours demander"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Ne pas autoriser"</string>
@@ -197,8 +197,8 @@
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Si la position exacte est désactivée, les applis ont accès à votre position approximative"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Autorisation d\'accès à \"<xliff:g id="PERM">%1$s</xliff:g>\""</string>
<string name="app_permission_header" msgid="2951363137032603806">"Accès à \"<xliff:g id="PERM">%1$s</xliff:g>\" pour cette appli"</string>
- <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="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Voir toutes les autorisations pour <xliff:g id="APP">%1$s</xliff:g>"</string>
+ <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Voir toutes les applis ayant 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 des applis inutilisées"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Supprimer les autorisations si l\'application n\'est pas utilisée"</string>
@@ -232,7 +232,7 @@
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Les applications disposant de cette autorisation peuvent consulter et modifier le journal d\'appels du téléphone"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"Les applications disposant de cette autorisation peuvent prendre des photos et enregistrer des vidéos"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"Les applications disposant de cette autorisation peuvent accéder à vos contacts"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Les applications disposant de cette autorisation peuvent accéder à la position de cet appareil"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Les applications ayant cette autorisation peuvent accéder à la position de cet appareil"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Les applis ayant cette autorisation peuvent détecter les appareils à proximité, s\'y connecter et déterminer leur position relative"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"Les applications disposant de cette autorisation peuvent enregistrer de l\'audio"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"Les applications disposant de cette autorisation peuvent passer et gérer des appels téléphoniques"</string>
@@ -246,8 +246,8 @@
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Aucun accès enregistré"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"Accès refusé/aucune tentative d\'accès"</string>
<string name="allowed_header" msgid="7769277978004790414">"Autorisé"</string>
- <string name="allowed_always_header" msgid="6455903312589013545">"Toujours autorisées"</string>
- <string name="allowed_foreground_header" msgid="6845655788447833353">"Autorisées seulement pendant l\'utilisation"</string>
+ <string name="allowed_always_header" msgid="6455903312589013545">"Toujours autorisé"</string>
+ <string name="allowed_foreground_header" msgid="6845655788447833353">"Autorisé seulement pendant l\'utilisation"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Autorisées à gérer les fichiers multimédias"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Autorisées à gérer tous les fichiers"</string>
<string name="ask_header" msgid="2633816846459944376">"Toujours demander"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Afficher la détection de l\'activation de l\'assistant"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Afficher une icône dans la barre d\'état lorsque le micro est utilisé pour activer l\'assistance vocale"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos et contenus multimédias sur votre appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à vos contacts ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position de cet appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"L\'application n\'a accès à la position de l\'appareil que lorsqu\'elle est ouverte"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position de cet appareil ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Cette appli peut vouloir accéder à votre position en permanence, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez-la à le faire dans les paramètres."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Changer l\'autorisation d\'accès à la position pour &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Cette appli souhaite accéder à votre position en permanence, même lorsque vous ne l\'utilisez pas. "<annotation id="link">"Autorisez-la à le faire dans les paramètres."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à détecter les appareils à proximité, s\'y connecter et déterminer leur position relative ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Autoriser <xliff:g id="APP_NAME">%1$s</xliff:g> à détecter les appareils à proximité, s\'y connecter et déterminer leur position relative ? "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Donner à <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> l\'accès à la position exacte et non plus approximative ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la position approximative de cet appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exacte"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approximative"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à votre agenda ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à envoyer et afficher des SMS ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos, contenus multimédias et fichiers sur votre appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux &lt;b&gt;photos, vidéos, fichiers musicaux/audio&lt;/b&gt; sur l\'appareil ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux &lt;b&gt;photos, vidéos, fichiers musicaux/audio, etc.&lt;/b&gt; sur l\'appareil ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à la musique et à l\'audio sur cet appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux photos et vidéos sur cet appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder à d\'autres photos et vidéos sur cet appareil ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à enregistrer de l\'audio ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Cette application ne pourra réaliser des enregistrements audio que lorsque vous l\'utiliserez"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; de réaliser des enregistrements audio ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Cette application peut souhaiter réaliser des enregistrements audio à tout moment, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Changer l\'autorisation d\'accès au micro pour &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Cette application souhaite réaliser des enregistrements audio à tout moment, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Autoriser <xliff:g id="APP_NAME">%1$s</xliff:g> à accéder aux données relatives à votre activité physique ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à prendre des photos et enregistrer des vidéos ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Cette application ne pourra prendre des photos et enregistrer des vidéos que lorsque vous l\'utiliserez"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à prendre des photos et enregistrer des vidéos ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Cette application peut souhaiter prendre des photos et des vidéos à tout moment, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Changer l\'autorisation d\'accès à l\'appareil photo pour &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Cette application souhaite prendre des photos et des vidéos à tout moment, même quand vous ne l\'utilisez pas. "<annotation id="link">"Autoriser dans les paramètres"</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à accéder aux données des capteurs concernant vos signes vitaux ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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 concernant vos signes vitaux ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Autorisations contrôlées"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> a accès à votre position"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Votre organisation autorise <xliff:g id="APP_NAME">%1$s</xliff:g> à accéder à votre position"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Autres autorisations"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Autorisation utilisée par le système"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Autorisations utilisées uniquement par les applications système."</string>
@@ -537,7 +589,7 @@
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Vérifier l\'état"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Paramètres de confidentialité"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Autres paramètres"</string>
- <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Accès à l\'appareil photo"</string>
+ <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Accès à la caméra"</string>
<string name="microphone_toggle_label_qs" msgid="8132912469813396552">"Accès au micro"</string>
<string name="permissions_removed_qs" msgid="8957319130625294572">"Autorisation supprimée"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"Voir l\'utilisation récente de l\'appareil photo"</string>
@@ -575,11 +627,11 @@
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Examiner l\'appli qui a accès à la localisation en arrière-plan"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> peut toujours accéder à votre localisation, même lorsque l\'appli est fermée"</string>
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Examiner l\'appli qui a accès à la localisation en arrière-plan"</string>
- <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Même fermée, cette appli peut toujours accéder à votre localisation.\n\nCertaines applis de sécurité et d\'urgence nécessitent d\'accéder à votre position en arrière-plan pour fonctionner comme prévu."</string>
+ <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Même fermée, cette appli peut toujours accéder à votre localisation.\n\nCertaines applis de sécurité et d\'urgence ont besoin d\'accéder à votre position en arrière-plan pour fonctionner comme prévu."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Accès modifié"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Voir l\'utilisation récente de la localisation"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Paramètres de confidentialité"</string>
- <string name="camera_toggle_title" msgid="1251201397431837666">"Accès à l\'appareil photo"</string>
+ <string name="camera_toggle_title" msgid="1251201397431837666">"Accès à la caméra"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Accès au micro"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"Pour les applis et services"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Pour les applis et services. Si ce paramètre est désactivé, il est possible que les données du micro soient quand même partagées quand vous appelez un numéro d\'urgence."</string>
@@ -591,8 +643,9 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Cette appli a indiqué qu\'elle peut partager des données de localisation avec des tiers"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Partage des données et localisation"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Origine des informations sur le partage des données"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Le développeur a fourni des infos au fabricant de cet appareil concernant la manière dont cette appli partage les données. Le développeur peut mettre à jour ces infos au fil du temps."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Le développeur a fourni des infos sur "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" concernant la manière dont cette appli partage les données. Le développeur peut mettre à jour ces infos au fil du temps."</string>
- <string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Appli peut partager données de localisation pour :"</string>
+ <string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"L\'appli peut partager données de localisation pour :"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Partage des données variable"</string>
<string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"La gestion des données peut varier selon la version de l\'appli, l\'utilisation que vous en faites, votre région et votre âge. "<annotation id="link">"En savoir plus sur le partage des données"</annotation></string>
<string name="permission_rationale_data_sharing_varies_message_without_link" msgid="4912763761399025094">"La gestion des données peut varier selon la version de l\'appli, l\'utilisation que vous en faites, votre région et votre âge."</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Sécurité des données"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Les données de localisation peuvent être partagées"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Cette appli a indiqué qu\'elle peut partager vos données de localisation avec des tiers"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Impossible d\'ouvrir ce lien"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Mises à jour du partage des données pour la localisation"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Consulter les applis qui ont modifié la manière dont elles peuvent partager vos données de localisation"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ces applis ont modifié la manière dont elles peuvent partager vos données de localisation. Elles ne les partageaient peut-être pas auparavant ou peuvent désormais les partager à des fins de publicité ou de marketing."</string>
@@ -619,7 +670,7 @@
<string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"Vos données de localisation sont désormais partagées avec des tiers à des fins de publicité ou de marketing"</string>
<string name="updated_in_last_days" msgid="8371811947153042322">"{count,plural, =0{Mise à jour au cours du dernier jour}=1{Mise à jour au cours du dernier jour}one{Mise à jour il y a # jour}many{Mise à jour au cours des # derniers jours}other{Mise à jour au cours des # derniers jours}}"</string>
<string name="no_updates_at_this_time" msgid="9031085635689982935">"Aucune mise à jour pour le moment"</string>
- <string name="safety_label_changes_notification_title" msgid="4479955083472203839">"Mises à jour du partage des données"</string>
+ <string name="safety_label_changes_notification_title" msgid="4479955083472203839">"Modifications du partage des données"</string>
<string name="safety_label_changes_notification_desc" msgid="7808764283266234675">"Certaines applis ont modifié la façon dont elles peuvent partager vos données de localisation"</string>
<string name="safety_label_changes_gear_description" msgid="2655887555599138509">"Paramètres"</string>
</resources>
diff --git a/PermissionController/res/values-gl-v33/strings.xml b/PermissionController/res/values-gl-v33/strings.xml
index 780f3faf6..3c8898c4f 100644
--- a/PermissionController/res/values-gl-v33/strings.xml
+++ b/PermissionController/res/values-gl-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Máis alertas"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertas pechadas"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Despregar tarxeta e ver 1 alerta máis}other{Despregar tarxeta e ver # alertas máis}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Acción completada"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Comproba as opcións de configuración que poden aumentar a protección do dispositivo"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Configuración rápida de seguranza e privacidade"</string>
diff --git a/PermissionController/res/values-gl/strings.xml b/PermissionController/res/values-gl/strings.xml
index e4f42ab90..1ed147b46 100644
--- a/PermissionController/res/values-gl/strings.xml
+++ b/PermissionController/res/values-gl/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Non permitir aínda así"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Pechar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Queres permitir á aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permitir sempre á aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Queres dar permiso á aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; para <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; poida <xliff:g id="ACTION">%2$s</xliff:g> sempre?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Só ao usar a aplicación"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Sempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Non permitir e non volver preguntar"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Abriuse por última vez o <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Se permites a xestión de todos os ficheiros, esta aplicación pode acceder aos ficheiros de almacenamento común, así como modificalos e eliminalos, neste dispositivo ou nos dispositivos de almacenamento conectados. A aplicación pode acceder aos ficheiros sen pedirche permiso."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Queres permite que esta aplicación acceda aos ficheiros, así como que os modifique e elimine, neste dispositivo ou en calquera dispositivo de almacenamento conectado? Esta aplicación pode acceder aos ficheiros sen pediche permiso."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"As aplicacións que teñen este permiso poden facer o seguinte: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"As aplicacións que teñen este permiso poden <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"As aplicacións que teñen este permiso poden acceder á túa actividade física, como as camiñadas, os percorridos en bicicleta, os traxectos en coche, o reconto de pasos e moito máis"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"As aplicacións que teñen este permiso poden acceder ao teu calendario"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"As aplicacións que teñen este permiso poden ler e editar o rexistro de chamadas do teléfono"</string>
@@ -444,7 +444,7 @@
<string name="incident_report_dialog_title" msgid="669104389325204095">"Queres compartir os datos de depuración?"</string>
<string name="incident_report_dialog_intro" msgid="5897733669850951832">"O sistema detectou un problema."</string>
<string name="incident_report_dialog_text" msgid="5675553296891757523">"A aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> quere subir un informe de erros deste dispositivo, xerado o <xliff:g id="DATE">%2$s</xliff:g> (<xliff:g id="TIME">%3$s</xliff:g>). Os informes de erros inclúen información persoal sobre o dispositivo ou datos rexistrados polas aplicacións, como os nomes de usuario, os datos de localización, os identificadores do dispositivo e a información da rede. Comparte estes informes unicamente con persoas e aplicacións de confianza. Queres permitir que a aplicación <xliff:g id="APP_NAME_1">%4$s</xliff:g> cargue un informe de erros?"</string>
- <string name="incident_report_error_dialog_text" msgid="4189647113387092272">"Houbo un erro ao procesar o informe de erro da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>, polo cal se denegou o uso compartido dos datos de depuración detallados. Lamentamos a interrupción."</string>
+ <string name="incident_report_error_dialog_text" msgid="4189647113387092272">"Houbo un erro ao procesar o informe de erros da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>, polo cal se denegou o uso compartido dos datos de depuración detallados. Lamentamos a interrupción."</string>
<string name="incident_report_dialog_allow_label" msgid="2970242967721155239">"Permitir"</string>
<string name="incident_report_dialog_deny_label" msgid="3535314290677579383">"Denegar"</string>
<string name="adjust_user_sensitive_title" msgid="4196724451314280527">"Configuración avanzada"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostrar detección do activador do asistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostra unha icona na barra de estado cando se utiliza o micrófono para activar o asistente de voz"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ás fotos, ao contido multimedia e aos ficheiros do teu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda aos teus contactos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á localización deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"A aplicación só terá acceso á localización mentres a esteas utilizando"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á localización deste dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Esta aplicación pode querer acceder á túa localización todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Queres cambiar o acceso da aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; á localización?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Esta aplicación quere acceder á túa localización todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; atope dispositivos próximos, se conecte a eles e determine a súa posición relativa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; atope dispositivos próximos, se conecte a eles e determine a súa posición relativa? "<annotation id="link">"Permitir na configuración"</annotation>"."</string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Queres que o acceso de <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> á localización cambie de aproximada a precisa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á localización aproximada deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precisa"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ao teu calendario?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envíe e vexa mensaxes SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a fotos, contido multimedia e ficheiros no teu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ás &lt;b&gt;fotos, vídeos, música e audio&lt;/b&gt; deste dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ás &lt;b&gt;fotos, vídeos, música, audio e outros ficheiros&lt;/b&gt; do dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á música e aos ficheiros de audio deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda ás fotos e aos vídeos deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a máis fotos e vídeos deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Esta aplicación só poderá gravar audio cando a esteas utilizando"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Pode que esta aplicación queira gravar audio todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Queres cambiar o acceso da aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ao micrófono?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Esta aplicación quere gravar audio todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda á túa actividade física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; realice fotos e grave vídeos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Esta aplicación só poderá sacar fotos e gravar vídeos cando a esteas utilizando"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; saque fotos e grave vídeos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Pode que esta aplicación queira sacar fotos e gravar vídeos todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Queres cambiar o acceso da aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; á cámara?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Esta aplicación quere sacar fotos e gravar vídeos todo o tempo, incluso cando non a esteas utilizando. "<annotation id="link">"Permitir en Configuración."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisos controlados"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ten acceso á localización"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"A túa organización permite que <xliff:g id="APP_NAME">%1$s</xliff:g> acceda á túa localización"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Outros permisos"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Permiso que utiliza o sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Permisos que só utilizan as aplicacións do sistema."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"A aplicación indicou que é posible que comparta datos de localización con terceiros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Uso compartido de datos e localización"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De onde provén a información sobre o uso compartido de datos?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"A persoa que programou esta aplicación facilitoulle información acerca de como comparte datos ao fabricante deste dispositivo. Esa persoa pode modificar esta información co paso do tempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"A persoa que programou esta aplicación facilitoulle información acerca de como comparte datos a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". É posible que esa persoa modifique esta información co paso do tempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"A app pode compartir datos de localización para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"As prácticas de uso compartido de datos varían"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Seguranza dos datos"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Poden compartirse os datos de localización"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Esta aplicación indicou que pode compartir os teus datos de localización con terceiros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Non se puido abrir esta ligazón"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Actualizacións do uso compartido de datos de localización"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Revisa as aplicacións que cambiaron a forma en que poden compartir os teus datos de localización"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Estas aplicacións cambiaron a forma en que poden compartir os teus datos de localización. É posible que non os compartisen antes ou que agora os compartan con fins publicitarios ou de márketing."</string>
diff --git a/PermissionController/res/values-gu-v33/strings.xml b/PermissionController/res/values-gu-v33/strings.xml
index 06ea8f9b2..d77558fc3 100644
--- a/PermissionController/res/values-gu-v33/strings.xml
+++ b/PermissionController/res/values-gu-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"વધુ અલર્ટ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"છોડી દીધેલા અલર્ટ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{મોટું કરો અને વધુ એક અલર્ટ જુઓ}one{મોટું કરો અને વધુ # અલર્ટ જુઓ}other{મોટું કરો અને વધુ # અલર્ટ જુઓ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"અલર્ટ. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ક્રિયા પૂર્ણ થઈ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"તમારા ડિવાઇસમાં સુરક્ષા ઉપાયો ઉમેરી શકે એવા સેટિંગ ચેક કરો"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"સુરક્ષા અને પ્રાઇવસી માટેના ઝડપી સેટિંગ"</string>
diff --git a/PermissionController/res/values-gu/strings.xml b/PermissionController/res/values-gu/strings.xml
index be4fbe77f..0fc0b52d8 100644
--- a/PermissionController/res/values-gu/strings.xml
+++ b/PermissionController/res/values-gu/strings.xml
@@ -130,7 +130,7 @@
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"અન્ય પરવાનગીઓ જુઓ"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> અને વધુ <xliff:g id="NUM">%3$s</xliff:g>"</string>
- <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"છેલ્લા 24 કલાકમાં ઍપ દ્વારા તમારા <xliff:g id="PERMGROUP">%1$s</xliff:g>નો ઉપયોગ ક્યારે કરવામાં આવ્યો, તેની સમયરેખા"</string>
+ <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"છેલ્લા 24 કલાકમાં ઍપ દ્વારા તમારા <xliff:g id="PERMGROUP">%1$s</xliff:g>નો ઉપયોગ ક્યારે કરવામાં આવ્યો, તેની ટાઇમલાઇન"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"છેલ્લા 7 દિવસમાં ઍપ દ્વારા તમારા <xliff:g id="PERMGROUP">%1$s</xliff:g>નો ઉપયોગ ક્યારે કરવામાં આવ્યો, તેની સમયરેખા"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"જ્યારે આ ઍપ દ્વારા તમારી <xliff:g id="PERMGROUP">%1$s</xliff:g>ની પરવાનગીનો ઉપયોગ કરવામાં આવ્યો"</string>
<string name="permission_usage_access_dialog_learn_more" msgid="7121468469493184613">"વધુ જાણો"</string>
@@ -226,13 +226,13 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"છેલ્લે <xliff:g id="DATE">%s</xliff:g>ના રોજ ખોલી"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"તમે બધી ફાઇલો મેનેજ કરવાની મંજૂરી આપશો, તો આ ઍપ, આ ડિવાઇસના સામાન્ય સ્ટોરેજમાં અથવા કનેક્ટ કરેલા સ્ટોરેજ ડિવાઇસમાં રહેલી કોઈપણ ફાઇલને ઍક્સેસ કરી શકશે, તેમાં ફેરફાર કરી શકશે અથવા તેને ડિલીટ કરી શકશે. ઍપ તમને પૂછ્યા વિના ફાઇલો ઍક્સેસ કરે તેમ બની શકે છે."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"ડિવાઇસમાં અથવા કનેક્ટ કરેલા સ્ટોરેજ ડિવાઇસમાં રહેલી ફાઇલોને ઍક્સેસ કરવાની, તેમાં ફેરફાર કરવાની અથવા તેને ડિલીટ કરવાની મંજૂરી આપીએ? આ ઍપ તમને પૂછ્યા વિના ફાઇલો ઍક્સેસ કરે તેમ બની શકે છે."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"આ પરવાનગી ધરાવતી ઍપ <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"આ પરવાનગી ધરાવતી ઍપ આ કરી શકે છે: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"આ પરવાનગી ધરાવતી ઍપ તમારી શારીરિક પ્રવૃત્તિ જેમ કે ચાલવું, બાઇકિંગ, ડ્રાઇવિંગ, પગલાંની સંખ્યા અને બીજી ઘણી બધી પ્રવૃત્તિ ઍક્સેસ કરી શકે છે"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"આ પરવાનગી ધરાવતી ઍપ તમારા કૅલેન્ડરને ઍક્સેસ કરી શકશે"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"આ પરવાનગી ધરાવતી ઍપ ફોન કૉલ લૉગ વાંચી અને લખી શકે છે"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"આ પરવાનગી ધરાવતી ઍપ ફોટા લઈ શકે છે અને વીડિયો રેકોર્ડ કરી શકે છે"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"આ પરવાનગી ધરાવતી ઍપ તમારા સંપર્કોને ઍક્સેસ કરી શકશે"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"આ પરવાનગી ધરાવતી ઍપ આ ડિવાઇસનું સ્થાન ઍક્સેસ કરી શકે છે"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"આ પરવાનગી ધરાવતી ઍપ આ ડિવાઇસનું લોકેશન ઍક્સેસ કરી શકે છે"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"આ પરવાનગી ધરાવતી ઍપ નજીકના ડિવાઇસ શોધી શકે છે, તેઓને કનેક્ટ કરી શકે છે તેમજ સંબંધિત અંતર નક્કી કરી શકે છે"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"આ પરવાનગી ધરાવતી ઍપ ઑડિયો રેકોર્ડ કરી શકશે"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"આ પરવાનગી ધરાવતી ઍપ ફોન કૉલ કરી શકશે અને તેને મેનેજ કરી શકશે"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"આસિસ્ટંટ ટ્રિગરની ઓળખ બતાવો"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"જ્યારે માઇક્રોફોનનો ઉપયોગ કરીને વૉઇસ આસિસ્ટંટ સક્રિય કરવામાં આવે, ત્યારે માઇક્રોફોનનું આઇકન સ્ટેટસ બારમાં બતાવો"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા ડિવાઇસ પર ફોટા અને મીડિયાને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા સંપર્કોને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસના સ્થાનને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"જ્યારે તમે ઍપનો ઉપયોગ કરી રહ્યા હશો માત્ર ત્યારે જ ઍપ સ્થાનને ઍક્સેસ કરી શકશે"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસના સ્થાનને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ તે હંમેશાં તમારા સ્થાનને ઍક્સેસ કરી શકે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; માટે સ્થાનનો ઍક્સેસ બદલીએ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ તે હંમેશાં તમારા સ્થાનને ઍક્સેસ કરવા માગે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને નજીકના ડિવાઇસને શોધવાની, તેને કનેક્ટ કરવાની તેમજ સંબંધિત અંતર નક્કી કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને નજીકના ડિવાઇસને શોધવાની, તેને કનેક્ટ કરવાની તેમજ સંબંધિત અંતર નક્કી કરવાની મંજૂરી આપીએ? "<annotation id="link">"સેટિંગમાં મંજૂરી આપો."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>નો સ્થાનનો ઍક્સેસ અંદાજિતમાંથી બદલીને ચોક્કસ કરીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસના અંદાજીત સ્થાનને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ચોક્કસ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"અંદાજિત"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા કૅલેન્ડરને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને SMS સંદેશા મોકલવા અને જોવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને SMS મેસેજ મોકલવા અને જોવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા ડિવાઇસ પરના ફોટા, મીડિયા અને ફાઇલોને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પરના &lt;/b&gt;ફોટા, વીડિયો, મ્યુઝિક અને ઑડિયો&lt;/b&gt;ના ઍક્સેસની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પર &lt;b&gt;ફોટા, વીડિયો, મ્યુઝિક, ઑડિયો અને અન્ય ફાઇલો&lt;b&gt;ના ઍક્સેસની મંજૂરી આપીએ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પરની મ્યુઝિક અને ઑડિયો ફાઇલો ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પરના ફોટા અને વીડિયો ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને આ ડિવાઇસ પરના વધુ ફોટા અને વીડિયો ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ઑડિયો રેકૉર્ડ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"જ્યારે તમે ઍપનો ઉપયોગ કરી રહ્યા હશો, માત્ર ત્યારે જ ઍપ ઑડિયો રેકોર્ડ કરી શકશે"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ઑડિયો રેકોર્ડ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ ઍપ હંમેશાં ઑડિયો રેકોર્ડ કરવાનું ઇચ્છી શકે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; માટે માઇક્રોફોનનો ઍક્સેસ બદલીએ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ ઍપ હંમેશાં ઑડિયો રેકોર્ડ કરવા માગે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારી શારીરિક પ્રવૃત્તિને ઍક્સેસ કરવાની મંજૂરી આપવી છે?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ફોટા પાડવાની અને વીડિયો રેકોર્ડ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"જ્યારે તમે ઍપનો ઉપયોગ કરી રહ્યા હશો, માત્ર ત્યારે જ ઍપ ફોટા લઈ શકશે અને વીડિયો રેકોર્ડ કરી શકશે"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ફોટા લેવાની અને વીડિયો રેકોર્ડ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ ઍપ હંમેશાં ફોટા લેવા અને વીડિયો રેકોર્ડ કરવાનું ઇચ્છી શકે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; માટે કૅમેરાનો ઍક્સેસ બદલીએ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"તમે આ ઍપનો ઉપયોગ કરી રહ્યાં ન હો, તો પણ ઍપ હંમેશાં ફોટા લેવા અને વીડિયો રેકોર્ડ કરવા માગે છે. "<annotation id="link">"સેટિંગમાંથી મંજૂરી આપો."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા ફોનના કૉલ લૉગ ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ફોન કૉલ કરવાની અને તેને મેનેજ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારા જીવિત હોવાના મહત્ત્વપૂર્ણ સંકેતો વિશેના સેન્સર ડેટાને ઍક્સેસ કરવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"જ્યારે તમે ઍપનો ઉપયોગ કરી રહ્યાં ન હો, ત્યારે પણ આ ઍપને બૉડી સેન્સરનો ડેટા ઍક્સેસ કરવાની મંજૂરી આપવા માટે, "<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="auto_granted_permissions" msgid="6009452264824455892">"નિયંત્રિત પરવાનગીઓ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"શું &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમને નોટિફિકેશન મોકલવાની મંજૂરી આપીએ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"નિયંત્રિત પરવાનગીઓ"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> પાસે લોકેશન ઍક્સેસ છે"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"તમારી સંસ્થા <xliff:g id="APP_NAME">%1$s</xliff:g>ને તમારું લોકેશન ઍક્સેસ કરવાની મંજૂરી આપે છે"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"અન્ય પરવાનગીઓ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"સિસ્ટમ દ્વારા ઉપયોગમાં લેવાતી પરવાનગીઓ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"ફક્ત સિસ્ટમ ઍપ્લિકેશન દ્વારા ઉપયોગમાં લેવાતી પરવાનગીઓ."</string>
@@ -518,7 +570,7 @@
<string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g>ને Android વડે સુરક્ષિત કરવામાં આવી છે. આ ડિવાઇસમાં તમારા ડેટા પર પ્રક્રિયા કરવામાં આવતી હોવાથી, આ ઍપની પરવાનગીના વપરાશની માહિતી તમારા પ્રાઇવસી ડૅશબોર્ડ પર બતાવવામાં આવતી નથી."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"ડિવાઇસનો કૅમેરા બ્લૉક કરેલો છે"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"ડિવાઇસનું માઇક્રોફોન બ્લૉક કરેલું છે"</string>
- <string name="blocked_location_title" msgid="2005608279812892383">"ડિવાઇસનું સ્થાન બંધ છે"</string>
+ <string name="blocked_location_title" msgid="2005608279812892383">"ડિવાઇસનું લોકેશન બંધ છે"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"ઍપ અને સેવાઓ માટે"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"જ્યારે તમે ઇમર્જન્સી નંબર પર કૉલ કરો ત્યારે કદાચ માઇક્રોફોનનો ડેટા હજી પણ શેર કરવામાં આવી શકે છે."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"બદલો"</string>
@@ -574,10 +626,10 @@
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"આ ઍપ Androidના નવીનતમ વર્ઝનને સપોર્ટ કરતી નથી. જો આ ઍપ મ્યુઝિક અને ઑડિયો ફાઇલોને ઍક્સેસ કરી શકતી ન હોય, તો તેને ફોટા અને વીડિયોને પણ ઍક્સેસ કરવાની મંજૂરી આપવામાં આવશે નહીં."</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"બૅકગ્રાઉન્ડમાં સ્થાનનો ઍક્સેસ ધરાવતી ઍપનો રિવ્યૂ કરો"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> હંમેશાં તમારા સ્થાનને ઍક્સેસ કરી શકે છે, ઍપ બંધ હોય ત્યારે પણ"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"બૅકગ્રાઉન્ડમાં સ્થાનનો ઍક્સેસ ધરાવતી ઍપનો રિવ્યૂ કરો"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"બૅકગ્રાઉન્ડમાં લોકેશનનો ઍક્સેસ ધરાવતી ઍપનો રિવ્યૂ કરો"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"આ ઍપ તમારું લોકેશન હંમેશાં ઍક્સેસ કરી શકે છે, તે બંધ હોય ત્યારે પણ.\n\nસલામતી અને ઇમર્જન્સી સેવા સંબંધી અમુક ઍપને ધાર્યા મુજબ કામ કરવા માટે, બૅકગ્રાઉન્ડમાં તમારા લોકેશનનો ઍક્સેસ હોવો આવશ્યક છે."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"ઍક્સેસ કરવા સંબંધિત પરવાનગી બદલાઈ ગઈ"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"સ્થાનનો તાજેતરનો વપરાશ જુઓ"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"લોકેશનનો તાજેતરનો વપરાશ જુઓ"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"પ્રાઇવસીને લગતાં નિયંત્રણ"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"કૅમેરાનો ઍક્સેસ"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"માઇક્રોફોનનો ઍક્સેસ"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"આ ઍપ દ્વારા જણાવવામાં આવ્યું છે કે તે ત્રીજા પક્ષો સાથે લોકેશન ડેટા શેર કરી શકે છે"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ડેટા શેરિંગ અને લોકેશન"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ડેટા શેરિંગ સંબંધિત માહિતી ક્યાંથી આવે છે"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ઍપના ડેવલપરે આ ઍપની ડેટા શેર કરવાની રીત વિશેની માહિતી આ ડિવાઇસના નિર્માતાને પૂરી પાડી છે. સમય જતાં કદાચ ડેવલપર આ માહિતી અપડેટ કરી શકે છે."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ઍપના ડેવલપરે આ ઍપની ડેટા શેર કરવા વિશેની માહિતી "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"ને પૂરી પાડી છે. સમય જતાં કદાચ ડેવલપર આ માહિતી અપડેટ કરી શકે છે."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"આ ઍપ આ માટે લોકેશન ડેટા શેર કરી શકે છે:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ડેટા શેરિંગમાં ફેરફાર થતો રહે છે"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ડેટા સલામતી"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"લોકેશન ડેટા શેર કરવામાં આવી શકે છે"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"આ ઍપ દ્વારા જણાવવામાં આવ્યું છે કે તે ત્રીજા પક્ષો સાથે તમારો લોકેશન ડેટા શેર કરી શકે છે"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"આ લિંક ખોલી શકાતી નથી"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"લોકેશન માટે ડેટા શેરિંગ સંબંધિત અપડેટ"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"તે ઍપનું રિવ્યૂ કરો જેમણે તમારા લોકેશન ડેટાને શેર કરવાની રીત બદલી છે"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"આ ઍપ દ્વારા તમારા લોકેશન ડેટાને શેર કરવાની રીત બદલવામાં આવી હોઈ શકે છે. તેઓએ તેને પહેલાં શેર કર્યો ન હોય એવું બની શકે છે અથવા હવે તેને જાહેરાત અથવા માર્કેટિંગ હેતુઓ માટે શેર કરી શકે છે."</string>
diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml
index ced18bd1e..019d1dd3e 100644
--- a/PermissionController/res/values-hi/strings.xml
+++ b/PermissionController/res/values-hi/strings.xml
@@ -32,11 +32,11 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"\"ऐप्लिकेशन इस्तेमाल करते समय\" अनुमति बनाए रखें"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“सिर्फ़ इस बार अनुमति दें” को बनाए रखें"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"ज़्यादा जानकारी"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"सभी को अनुमति दें"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"सभी के लिए अनुमति दें"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"हमेशा के लिए सभी को अनुमति दें"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"फ़ोटो और वीडियो चुनें"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"चुनिंदा फ़ोटो और वीडियो को अनुमति दें"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"ज़्यादा फ़ोटो चुनें"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"ज़्यादा डेटा न चुनें"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"ज़्यादा फ़ोटो और वीडियो न चुनें"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"फिर भी अनुमति न दें"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"खारिज करें"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> में से <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"जगह की सटीक जानकारी का इस्तेमाल करें"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"जगह की सटीक जानकारी देने वाली सुविधा बंद होने पर, ऐप्लिकेशन आपकी अनुमानित जगह की जानकारी को ऐक्सेस कर सकते हैं"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> की अनुमति"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"इस ऐप्लिकेशन के लिए <xliff:g id="PERM">%1$s</xliff:g> की अनुमति चाहिए"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"इस ऐप्लिकेशन के लिए, <xliff:g id="PERM">%1$s</xliff:g> ऐक्सेस करने की अनुमति चाहिए"</string>
<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>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"पिछली बार <xliff:g id="DATE">%s</xliff:g> को खोला गया था"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"अगर आप इस ऐप्लिकेशन को सभी फ़ाइलों को मैनेज करने की अनुमति देते हैं, तो यह ऐप्लिकेशन इस डिवाइस या इससे जुड़े दूसरे डिवाइस के स्टोरेज में मौजूद किसी भी फ़ाइल को ऐक्सेस कर सकता है, उनमें बदलाव कर सकता है, और उन्हें मिटा भी सकता है. यह ऐप्लिकेशन आपसे पूछे बिना फ़ाइलें ऐक्सेस कर सकता है."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"क्या आप इस ऐप्लिकेशन को इस डिवाइस या इससे जुड़े दूसरे डिवाइस के स्टोरेज में मौजूद फ़ाइलें ऐक्सेस करने, उनमें बदलाव करने, और उन्हें मिटाने की अनुमति देना चाहते हैं? यह ऐप्लिकेशन आपसे पूछे बिना फ़ाइलें ऐक्सेस कर सकता है."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"इस अनुमति वाले ऐप्लिकेशन <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"इस अनुमति वाले ऐप्लिकेशन यह कर सकते हैं: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"इसकी अनुमति वाले ऐप्लिकेशन, आपकी शारीरिक गतिविधियों की जानकारी ऐक्सेस कर सकते हैं. इसमें पैदल चलने, बाइक चलाने, गाड़ी चलाने, और कदमों की संख्या जैसी कई जानकारी शामिल है"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"इस अनुमति वाले ऐप्लिकेशन आपके कैलेंडर को ऐक्सेस कर सकते हैं"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"ऐसे ऐप्लिकेशन जिनके पास अनुमति है, वे फ़ोन में कॉल लॉग को पढ़ सकते हैं और लिख सकते हैं"</string>
@@ -397,9 +397,9 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं को पढ़ सकेगा और उन पर कार्रवाई कर पाएगा. साथ ही, यह आपके फ़ोन, एसएमएस, संपर्कों, और कैलेंडर की अनुमतियों को भी ऐक्सेस कर पाएगा."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> आपकी सूचनाओं पर कार्रवाई कर पाएगा. साथ ही, यह आपके कनेक्ट किए गए डिवाइस पर, आपके ऐप्लिकेशन का कॉन्टेंट चला पाएगा."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"यह सेवा आपके फ़ोन की फ़ोटो, मीडिया, और सूचनाओं को दूसरे डिवाइसों पर शेयर करती है."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"नोट लेने का डिफ़ॉल्ट ऐप्लिकेशन"</string>
- <string name="role_notes_short_label" msgid="8796604147546125285">"नोट लेने के लिए ऐप्लिकेशन"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"आपके डिवाइस पर नोट लेने की सुविधा देने वाले ऐप्लिकेशन"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"नोट लिखने का डिफ़ॉल्ट ऐप्लिकेशन"</string>
+ <string name="role_notes_short_label" msgid="8796604147546125285">"नोट लिखने के लिए ऐप्लिकेशन"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"आपके डिवाइस पर नोट लिखने की सुविधा देने वाले ऐप्लिकेशन"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"नोट"</string>
<string name="request_role_current_default" msgid="738722892438247184">"मौजूदा डिफ़ॉल्ट"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"फिर से न पूछें"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"असिस्टेंट ऐप्लिकेशन का माइक्रोफ़ोन चालू है या बंद, इसकी सूचना दिखाएं"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"आवाज़ से डिवाइस का इस्तेमाल करने के लिए, माइक्रोफ़ोन का इस्तेमाल करते समय स्थिति बार में आइकॉन दिखाएं"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने डिवाइस में मौजूद फ़ोटो और मीडिया ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने संपर्क देखने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस की जगह की जानकारी ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ऐप्लिकेशन, डिवाइस की जगह की जानकारी सिर्फ़ तभी देख पाएगा जब आप इसका इस्तेमाल कर रहे हों"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस की जगह की जानकारी ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"यह ऐप्लिकेशन शायद आपके डिवाइस की जगह की जानकारी हर समय ऐक्सेस करना चाहता है. उस समय भी जब आप इसका इस्तेमाल न कर रहे हों. "<annotation id="link">"सेटिंग में इसकी अनुमति दें."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; के लिए जगह की जानकारी का ऐक्सेस बदलना चाहते हैं?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"यह ऐप्लिकेशन आपके डिवाइस की जगह की जानकारी हर समय ऐक्सेस करना चाहता है. उस समय भी जब आप इसका इस्तेमाल न कर रहे हों. "<annotation id="link">"सेटिंग में इसकी अनुमति दें."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"क्या आपको &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को आस-पास मौजूद डिवाइसों को खोजने, उनसे कनेक्ट करने, और उनकी जगह की जानकारी का पता लगाने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को आस-पास मौजूद डिवाइसों को खोजने, उनसे कनेक्ट करने, और उनकी जगह की जानकारी का पता लगाने की अनुमति देना चाहते हैं? "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"क्या <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> आपकी जगह की अनुमानित जानकारी के बजाय सटीक जानकारी ऐक्सेस करे?"</string>
- <string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस की जगह की अनुमानित जानकारी ऐक्सेस करने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
+ <string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"क्या आपको &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस की जगह की अनुमानित जानकारी ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"सटीक जगह"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"अनुमानित जगह"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपना कैलेंडर ऐक्सेस करने की अनुमति देना है?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को एसएमएस (मैसेज) भेजने और देखने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस पर मौजूद फ़ोटो, ऑडियो-वीडियो, और फ़ाइलें ऐक्सेस करने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस में मौजूद &lt;b&gt;फ़ोटो, वीडियो, संगीत, और ऑडियो&lt;/b&gt; का ऐक्सेस देना है?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को डिवाइस में मौजूद &lt;b&gt;फ़ोटो, वीडियो, संगीत, ऑडियो, और अन्य फ़ाइल&lt;/b&gt; का ऐक्सेस देना है?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस में मौजूद संगीत और ऑडियो ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस में मौजूद फ़ोटो और वीडियो ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"क्या &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को इस डिवाइस पर मौजूद अन्य फ़ोटो और वीडियो का ऐक्सेस देना है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को ऑडियो रिकॉर्ड करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ऐप्लिकेशन सिर्फ़ तब ही ऑडियो रिकॉर्ड कर पाएगा, जब आप ऐप्लिकेशन इस्तेमाल कर रहे हों"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को ऑडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"यह ऐप्लिकेशन हर समय ऑडियो रिकॉर्ड कर सकता है. ऐप्लिकेशन इस्तेमाल न करने पर भी ऐसा हो सकता है. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; के लिए, माइक्रोफ़ोन के ऐक्सेस की अनुमति बदलना चाहते हैं?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"यह ऐप्लिकेशन हर समय ऑडियो रिकॉर्ड करना चाहता है, तब भी जब आप ऐप्लिकेशन इस्तेमाल न कर रहे हों. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपनी शारीरिक गतिविधि की जानकारी पाने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोटो खींचने और वीडियो रिकॉर्ड करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ऐप्लिकेशन सिर्फ़ तब ही तस्वीरें ले पाएगा और वीडियो रिकॉर्ड कर पाएगा, जब आप ऐप्लिकेशन इस्तेमाल कर रहे हों"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को तस्वीरें लेने और वीडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"यह ऐप्लिकेशन हर समय तस्वीरें ले सकता है और वीडियो रिकॉर्ड कर सकता है. ऐप्लिकेशन इस्तेमाल न करने पर भी ऐसा हो सकता है. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"क्या आप &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; के लिए, कैमरे के ऐक्सेस की अनुमति बदलना चाहते हैं?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"यह ऐप्लिकेशन हर समय तस्वीरें लेना और वीडियो रिकॉर्ड करना चाहता है, तब भी जब आप ऐप्लिकेशन इस्तेमाल न कर रहे हों. "<annotation id="link">"सेटिंग में जाकर अनुमति दें."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने फ़ोन के काॅल लाॅग को ऐक्सेस करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोन कॉल करने और उन्हें मैनेज करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने स्वास्थ्य से जुड़ी ज़रूरी जानकारी इस्तेमाल करने की अनुमति देनी है?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"इस ऐप्लिकेशन का इस्तेमाल न किए जाने पर भी, इसे बॉडी सेंसर के डेटा को हमेशा ऐक्सेस करने की अनुमति देने के लिए, "<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को सूचनाएं भेजने की अनुमति दें?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"कंट्रोल की गई अनुमतियां"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> के पास, डिवाइस की जगह की जानकारी का ऐक्सेस है"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"आपके संगठन ने <xliff:g id="APP_NAME">%1$s</xliff:g> को, डिवाइस की जगह की जानकारी का ऐक्सेस दिया है"</string>
@@ -582,13 +636,14 @@
<string name="perm_toggle_description" msgid="7801326363741451379">"ऐप्लिकेशन और सेवाओं के लिए"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"ऐप्लिकेशन और सेवाओं के लिए. इस सेटिंग के बंद होने पर भी, माइक्रोफ़ोन डेटा को शेयर किया जा सकता है. ऐसा तब होता है, जब किसी आपातकालीन नंबर पर कॉल किया जाता है."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"उन ऐप्लिकेशन और सेवाओं को देखें जिनके पास जगह की जानकारी का ऐक्सेस है"</string>
- <string name="show_clip_access_notification_title" msgid="5168467637351109096">"क्लिपबोर्ड का डेटा ऐक्सेस किए जाने पर मैसेज पाएं"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"जब कोई ऐप्लिकेशन आपके कॉपी किए गए टेक्स्ट, इमेज या अन्य कॉन्टेंट को ऐक्सेस करे, तो मैसेज से इसकी सूचना पाएं"</string>
+ <string name="show_clip_access_notification_title" msgid="5168467637351109096">"क्लिपबोर्ड का डेटा ऐक्सेस किए जाने पर मैसेज दिखाएं"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"जब कोई ऐप्लिकेशन आपके कॉपी किए गए टेक्स्ट, इमेज या अन्य कॉन्टेंट को ऐक्सेस करे, तो मैसेज दिखाएं"</string>
<string name="show_password_title" msgid="2877269286984684659">"पासवर्ड दिखाएं"</string>
<string name="show_password_summary" msgid="1110166488865981610">"टाइप करते समय वर्ण दिखाएं"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"इस ऐप्लिकेशन ने बताया है कि यह जगह की जानकारी का डेटा, तीसरे पक्ष के साथ शेयर कर सकता है"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"डेटा शेयर करने का तरीका और जगह की जानकारी"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"डेटा शेयर करने के तरीके की जानकारी यहां से मिलती है:"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"डेवलपर ने डिवाइस बनाने वाली कंपनी को, इस ऐप्लिकेशन के डेटा शेयर करने के तरीकों की जानकारी दी है. डेवलपर समय-समय पर इस जानकारी को अपडेट कर सकता है."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"डेवलपर ने "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" पर, इस ऐप्लिकेशन के डेटा शेयर करने के तरीकों की जानकारी दी है. डेवलपर समय-समय पर इस जानकारी को अपडेट कर सकता है."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ऐप जगह की जानकारी का डेटा इनके लिए शेयर करता है:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"डेटा शेयर करने के अलग-अलग तरीके"</string>
@@ -606,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"डेटा की सुरक्षा"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"जगह की जानकारी का डेटा शेयर किया जा सकता है"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"इस ऐप्लिकेशन में बताया गया है कि यह तीसरे पक्ष के साथ जगह की जानकारी का डेटा शेयर कर सकता है"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"यह लिंक नहीं खोला जा सका"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"जगह की जानकारी का डेटा शेयर करने के तरीके के बारे में अपडेट"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"ऐसे ऐप्लिकेशन देखें जिन्होंने आपकी जगह की जानकारी के डेटा को शेयर करने का तरीका बदल दिया है"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"ऐसे ऐप्लिकेशन देखें जिन्होंने शायद आपकी जगह की जानकारी के डेटा को शेयर करने का तरीका बदल दिया है"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"इन ऐप्लिकेशन ने आपकी जगह की जानकारी के डेटा को शेयर करने का तरीका बदल दिया है. ऐसा हो सकता है कि ये ऐप्लिकेशन पहले जगह की जानकारी का डेटा शेयर न करते हों या फिर अब विज्ञापन या मार्केटिंग के लिए यह डेटा शेयर किया हो."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"इन ऐप्लिकेशन के डेवलपर ने किसी ऐप स्टोर पर डेटा शेयर करने के उनके तरीकों की जानकारी बताई है. वे समय-समय पर इस जानकारी को अपडेट कर सकते हैं.\n\nडेटा शेयर करने के तरीके अलग-अलग हो सकते हैं. ये आपकी जगह, उम्र, ऐप्लिकेशन के वर्शन, और उसके इस्तेमाल के हिसाब से तय किए जाते हैं."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"डेटा शेयर करने की नीतियों के बारे में जानें"</string>
diff --git a/PermissionController/res/values-hr-v33/strings.xml b/PermissionController/res/values-hr-v33/strings.xml
index 648afedea..a50e58158 100644
--- a/PermissionController/res/values-hr-v33/strings.xml
+++ b/PermissionController/res/values-hr-v33/strings.xml
@@ -30,10 +30,9 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Više upozorenja"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Odbačena upozorenja"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Proširite i pogledajte još jedno upozorenje}one{Proširite i pogledajte još # upozorenje}few{Proširite i pogledajte još # upozorenja}other{Proširite i pogledajte još # upozorenja}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Upozorenje. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Radnja je dovršena"</string>
- <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Provjerite postavke koje mogu vašem uređaju dodati zaštitu"</string>
+ <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Provjerite postavke kojima možete dodatno zaštititi svoj uređaj"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Brze postavke sigurnosti i privatnosti"</string>
<string name="safety_center_qs_close_button" msgid="1352313308176244599">"Zatvori"</string>
<string name="safety_center_qs_expand_action" msgid="2193190557696484169">"Opcije proširivanja i prikazivanja"</string>
diff --git a/PermissionController/res/values-hr-v34/strings.xml b/PermissionController/res/values-hr-v34/strings.xml
index 822862be3..74a1d7d1e 100644
--- a/PermissionController/res/values-hr-v34/strings.xml
+++ b/PermissionController/res/values-hr-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Sigurnost i privatnost"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Kontrole"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Upravljajte pristupom aplikacija podacima o zdravlju"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Upravljajte kojim podacima o zdravlju pristupaju aplikacije"</string>
<string name="location_settings" msgid="8863940440881290182">"Pristup lokaciji"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Za aplikacije i usluge. Ako je ta postavka isključena, podaci mikrofona i dalje se mogu dijeliti kad nazovete broj hitne službe"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Za aplikacije i usluge"</string>
diff --git a/PermissionController/res/values-hr/strings.xml b/PermissionController/res/values-hr/strings.xml
index 3f0121378..180407eab 100644
--- a/PermissionController/res/values-hr/strings.xml
+++ b/PermissionController/res/values-hr/strings.xml
@@ -36,12 +36,12 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Uvijek dopusti sve"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Odaberite slike i videozapise"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Odaberite više"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Nemojte odabrati više"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Nemoj dopustiti"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ipak nemoj dopustiti"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Odbaci"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Želite li uvijek dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sljedeće: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Dopuštate li da aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; može <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Dopuštate li da aplikacija &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; može <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Samo dok se aplikacija koristi"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Uvijek"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Nemoj dopustiti i više ne pitaj"</string>
@@ -126,7 +126,7 @@
<string name="app_name_unknown" msgid="1319665005754048952">"Nepoznato"</string>
<string name="permission_usage_title" msgid="1568233336351734538">"Nadzorna ploča za privatnost"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Prikaz aplikacija koje su nedavno upotrebljavale dopuštenja"</string>
- <string name="permission_group_usage_title" msgid="2595013198075285173">"Upotreba grupe dopuštenja: <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
+ <string name="permission_group_usage_title" msgid="2595013198075285173">"Upotreba dopuštenja: <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Pogledajte ostala dopuštenja"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> i još <xliff:g id="NUM">%3$s</xliff:g>"</string>
@@ -356,7 +356,7 @@
<string name="role_browser_request_title" msgid="2895200507835937192">"Želite li postaviti aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> kao zadanu aplikaciju za preglednik?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"Nije potrebno nijedno dopuštenje"</string>
<string name="role_dialer_label" msgid="1100224146343237968">"Zadana aplikacija telefona"</string>
- <string name="role_dialer_short_label" msgid="7186888549465352489">"Aplikacija telefona"</string>
+ <string name="role_dialer_short_label" msgid="7186888549465352489">"Aplikacija za pozive"</string>
<string name="role_dialer_description" msgid="8768708633696539612">"Aplikacije koje vam omogućuju upućivanje i primanje telefonskih poziva na uređaju"</string>
<string name="role_dialer_request_title" msgid="5959618560705912058">"Želite li postaviti aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> kao svoju zadanu aplikaciju telefona?"</string>
<string name="role_dialer_request_description" msgid="6288839625724909320">"Aplikacija će dobiti pristup vašoj kameri, kontaktima, mikrofonu, telefonu i SMS-ovima"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Prikaz otkrivanja okidača asistenta"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Prikazuje ikonu na traci statusa kada se za aktiviranje glasovne pomoći upotrebljava mikrofon"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa fotografijama i medijima na vašem uređaju?"</string>
- <string name="permgrouprequest_contacts" msgid="8391550064551053695">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa vašim kontaktima?"</string>
- <string name="permgrouprequest_location" msgid="6990232580121067883">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
+ <string name="permgrouprequest_contacts" msgid="8391550064551053695">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da pristupa vašim kontaktima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
+ <string name="permgrouprequest_location" msgid="6990232580121067883">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacija će imati pristup lokaciji samo dok upotrebljavate aplikaciju"</string>
- <string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa lokaciji ovog uređaja?"</string>
+ <string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da pristupa lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ova aplikacija možda će uvijek htjeti imati pristup vašoj lokaciji, čak i kad je ne koristite. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Želite li promijeniti pristup lokaciji za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ova aplikacija želi uvijek pristupati vašoj lokaciji, čak i kad je ne koristite. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Dopustiti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; traži uređaje u blizini, poveže se s njima i odredi njihov približni položaj?"</string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da traži uređaje u blizini, povezuje se s njima i određuje njihov približni položaj?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Dopustiti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; traži uređaje u blizini, poveže se s njima i odredi njihov približni položaj? "<annotation id="link">"Dopustite u postavkama."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Želite li aplikaciji <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> promijeniti pristup iz približne lokacije u točnu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa približnoj lokaciji ovog uređaja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Točno"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Približno"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa vašem kalendaru?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da šalje i pregledava SMS poruke?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da pristupa fotografijama, medijima i datotekama na vašem uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup &lt;b&gt;foto/video/audiodatotekama i glazbi&lt;/b&gt; na ovom uređaju?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Dopustiti apl. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup &lt;b&gt;foto/video/audio i drugim datotekama te glazbi&lt;/b&gt; na uređaju?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup glazbi i audiodatotekama na ovom uređaju?"</string>
- <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup fotografijama i videozapisima na ovom uređaju?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristup većem broju fotografija i videozapisa na ovom uređaju?"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima audiozapise?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
+ <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti pristup fotografijama i videozapisima na ovom uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti pristup većem broju fotografija i videozapisa na ovom uređaju?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da snima audiozapise?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacija će moći snimati audiozapise samo dok je upotrebljavate"</string>
- <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima audiozapise?"</string>
+ <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da snima audiozapise?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Aplikacija će možda snimati audiozapise u svakom trenutku, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Želite li promijeniti pristup mikrofonu za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Aplikacija traži dopuštenje za snimanje audiozapisa u svakom trenutku, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Želite li dopustiti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pristupa vašoj tjelesnoj aktivnosti?"</string>
- <string name="permgrouprequest_camera" msgid="5123097035410002594">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima fotografije i videozapise?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
+ <string name="permgrouprequest_camera" msgid="5123097035410002594">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da snima fotografije i videozapise?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacija će moći snimati fotografije i videozapise samo dok je upotrebljavate"</string>
- <string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima fotografije i videozapise?"</string>
+ <string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da snima fotografije i videozapise?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Aplikacija će možda snimati fotografije i videozapise u svakom trenutku, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Želite li promijeniti pristup kameri za aplikaciju &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Aplikacija traži dopuštenje za snimanje fotografija i videozapisa u svakom trenutku, čak i kad je ne upotrebljavate. "<annotation id="link">"Dopustite u postavkama."</annotation></string>
- <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_calllog" msgid="2065327180175371397">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da pristupa zapisnicima poziva vašeg telefona?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
+ <string name="permgrouprequest_phone" msgid="1829234136997316752">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da upućuje telefonske pozive i upravlja njima?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrolirana dopuštenja"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Želite li aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dopustiti da vam šalje obavijesti?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolirana dopuštenja"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ima pristup lokaciji"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Vaša organizacija dopušta da <xliff:g id="APP_NAME">%1$s</xliff:g> pristupa vašoj lokaciji"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Ostala dopuštenja"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Dopuštenja koja upotrebljava sustav"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Dopuštenja koja upotrebljavaju samo aplikacije sustava."</string>
@@ -549,7 +601,7 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"Nedavno je koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"Koristi aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"Nedavno koristila aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"Koristi aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"Za aplikacije i usluge. Ako je ta postavka isključena, podaci mikrofona i dalje se mogu dijeliti kad nazovete broj hitne službe."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Pogledajte aplikacije i usluge koje imaju pristup lokaciji"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Prikaži pristup međuspremniku"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Primite poruku kad aplikacije pristupe tekstu, slikama ili drugom kopiranom sadržaju"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Prikazuje se poruka kad aplikacije pristupe tekstu, slikama ili drugom kopiranom sadržaju"</string>
<string name="show_password_title" msgid="2877269286984684659">"Prikaži zaporke"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Nakratko prikaži znakove tijekom unosa"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Znakovi se nakratko prikazuju tijekom unosa"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Aplikacija je navela da može dijeliti podatke o lokaciji s trećim stranama"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Dijeljenje podataka i lokacije"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Tko određuje kako se podaci dijele"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Razvojni programer pružio je proizvođaču ovog uređaja informacije o načinu na koji ova aplikacija dijeli podatke. Razvojni programer može s vremenom ažurirati te informacije."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Razvojni programer je usluzi "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" poslao informacije o načinu na koji aplikacija dijeli podatke. Razvojni programer može s vremenom ažurirati informacije."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Aplikacija može dijeliti podatke o lokaciji radi:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Način dijeljenja može se razlikovati"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Sigurnost podataka"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Podaci o lokaciji mogu se dijeliti"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Aplikacija je navela da vaše podatke o lokaciji može dijeliti s trećim stranama"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Vezu nije moguće otvoriti"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Ažuriranja o dijeljenju podataka za lokaciju"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Pregledajte aplikacije koje su promijenile način na koji mogu dijeliti vaše podatke o lokaciji"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ove su aplikacije promijenile način na koji mogu dijeliti vaše podatke o lokaciji. Ranije ih možda nisu dijelile ili ih sada mogu dijeliti u svrhe oglašavanja ili marketinga."</string>
diff --git a/PermissionController/res/values-hu-v33/strings.xml b/PermissionController/res/values-hu-v33/strings.xml
index d906e63d2..ee454fc12 100644
--- a/PermissionController/res/values-hu-v33/strings.xml
+++ b/PermissionController/res/values-hu-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Több értesítés"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Elvetett értesítések"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Ha kibontja, még egy értesítést láthat}other{Ha kibontja, még # értesítést láthat}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Figyelmeztetés. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Művelet befejezve"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Tekintse át a beállításokat, amelyek növelhetik eszköze védelmét"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Biztonsági és adatvédelmi gyorsbeállítások"</string>
diff --git a/PermissionController/res/values-hu/strings.xml b/PermissionController/res/values-hu/strings.xml
index e1bd29599..623b8760d 100644
--- a/PermissionController/res/values-hu/strings.xml
+++ b/PermissionController/res/values-hu/strings.xml
@@ -34,9 +34,9 @@
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Bővebben"</string>
<string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Összes engedélyezése"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Összes engedélyezése mindig"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Jelöljön ki fotókat, videókat"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Fotók és videók kijelölése"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Több kijelölése"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ne válasszon ki többet"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Nem jelölök ki többet"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Semmiképpen se engedélyezze"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Elvetés"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>/<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Segédet aktiváló parancsok észlelésének megjelenítése"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Ikon megjelenítése az állapotsoron, amikor a rendszer a mikrofont használja a hangsegéd aktiválásához"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"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 eszközön tárolt fotókhoz és médiatartalmakhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"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 a névjegyekhez?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"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 eszköz helyadataihoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Az alkalmazás csak akkor férhet hozzá a helyadatokhoz, amikor Ön használja az alkalmazást"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"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 eszköz helyadataihoz?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Előfordulhat, hogy az alkalmazás akkor is hozzá szeretne férni a helyadataihoz, amikor nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Megváltoztatja a helyadatokhoz 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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Az alkalmazás akkor is hozzá szeretne férni az Ön helyadataihoz, amikor Ön nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; megkeresheti a közeli eszközöket, meghatározhatja relatív pozíciójukat, és csatlakozhat hozzájuk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"A(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; megkeresheti a közeli eszközöket, meghatározhatja relatív pozíciójukat, és csatlakozhat hozzájuk? "<annotation id="link">"Engedélyezés a beállításokban."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Megváltoztatja a(z) <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> helyhozzáférését hozzávetőlegesről pontosra?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"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 eszköz hozzávetőleges helyadataihoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Pontos"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Hozzávetőleges"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"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 a naptárhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy SMS-eket küldhessen és tekinthessen meg?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"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 eszközön tárolt fotókhoz, médiatartalmakhoz és fájlokhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Hozzáférhet a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; az eszközön lévő &lt;b&gt;fotókhoz, videókhoz, zenékhez és hangfájlokhoz&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Hozzáférhet a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; az eszközön tárolt &lt;b&gt;fotókhoz, hang-, videó- és egyéb fájlokhoz&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Hozzáférhet a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; az eszközön tárolt zenékhez és egyéb hanganyagokhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Hozzáférhet a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; az eszközön tárolt fotókhoz és videókhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"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 eszközön tárolt további fotókhoz és videókhoz?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hangfelvételt készíthessen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Az alkalmazás csak akkor tud majd hangfelvételt készíteni, amikor Ön használja az alkalmazást."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hangfelvételt készíthessen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Lehet, hogy az alkalmazás akkor is szeretne hangfelvételt készíteni, amikor Ön nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Módosítja a mikrofonhoz 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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Az alkalmazás akkor is szeretne hangfelvételt készíteni, amikor Ön nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára a testmozgási adataihoz való hozzáférést?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy képeket és videókat készíthessen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Az alkalmazás csak akkor tud majd fényképeket és videókat készíteni, amikor Ön használja az alkalmazást."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy fényképeket és videókat készíthessen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Lehet, hogy az alkalmazás akkor is szeretne fotókat és videókat készíteni, amikor Ön nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Módosítja a kamerához 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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Az alkalmazás akkor is szeretne fényképeket és videókat készíteni, amikor Ön nem használja az alkalmazást. "<annotation id="link">"A beállításokban engedélyezheti."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Szabályozott engedélyek"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Szabályozott engedélyek"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> hozzáfér a tartózkodási helyhez"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Szervezete lehetővé teszi a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> számára, hogy hozzáférjen az Ön tartózkodási helyéhez"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"További engedélyek"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Rendszer által használt engedélyek"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Csak rendszeralkalmazások által használt engedélyek."</string>
@@ -523,7 +575,7 @@
<string name="blocked_mic_summary" msgid="8960466941528458347">"Segélyhívó szám hívásakor a rendszer továbbra is megoszthatja a mikrofonadatokat."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Módosítás"</string>
<string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Biztonság és adatvédelem"</string>
- <string name="safety_center_rescan_button" msgid="4517514567809409596">"Keresés az eszközön"</string>
+ <string name="safety_center_rescan_button" msgid="4517514567809409596">"Eszközvizsgálat"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"Elvetés"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"Elveti ezt az értesítést?"</string>
<string name="safety_center_issue_card_dismiss_confirmation_message" msgid="3775418736671093563">"Bármikor áttekintheti biztonsági és adatvédelmi beállításait, és növelheti a védelmet"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Az alkalmazás jelezte, hogy megoszthat helyadatokat harmadik felekkel"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Adatmegosztás és hely"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Az adatmegosztással kapcsolatos információ forrása"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"A fejlesztő információt adott meg az eszköz gyártójának arról, hogy az alkalmazás minként oszt meg adatokat. A fejlesztő idővel módosíthatja ezt az információt."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"A fejlesztő információt adott meg "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" számára arról, hogy az alkalmazás miként oszt meg adatokat. A fejlesztő idővel módosíthatja ezt az információt."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Az app helyadatokat oszthat meg az alábbi célból:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Az adatmegosztás változik"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Adatbiztonság"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Az alkalmazás megoszthat helyadatokat"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Az alkalmazás jelezte, hogy megoszthatja az Ön helyadatait harmadik felekkel"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Nem sikerült megnyitni a linket"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"A helyadatok megosztását érintő frissítések"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Áttekintheti az appokat, amelyek módosították, hogy miként oszthatják meg a helyadatait"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ezek az alkalmazások módosították, hogy miként oszthatják meg az Ön helyadatait. Előfordulhat, hogy korábban nem osztották meg az adatokat, illetve ezentúl hirdetési vagy marketing célokra oszthatják meg őket."</string>
diff --git a/PermissionController/res/values-hy-v33/strings.xml b/PermissionController/res/values-hy-v33/strings.xml
index d8836f16a..6efb079ef 100644
--- a/PermissionController/res/values-hy-v33/strings.xml
+++ b/PermissionController/res/values-hy-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Այլ ծանուցումներ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Անտեսված ծանուցումներ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Ծավալել և տեսնել ևս մեկ զգուշացում}one{Ծավալել և տեսնել ևս # զգուշացում}other{Ծավալել և տեսնել ևս # զգուշացում}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Ծանուցում։ <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Գործողությունն ավարտված է"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Ծանոթացեք կարգավորումներին, որոնց օգնությամբ կարող եք բարձրացնել ձեր սարքի անվտանգության մակարդակը"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Անվտանգության և գաղտնիության արագ կարգավորումներ"</string>
diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml
index f1aa222cc..f685014ef 100644
--- a/PermissionController/res/values-hy/strings.xml
+++ b/PermissionController/res/values-hy/strings.xml
@@ -34,9 +34,9 @@
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Մանրամասն"</string>
<string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Թույլատրել բոլորը"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Միշտ թույլատրել բոլորը"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Ընտրել լուսանկարներ և տեսանյութեր"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Կոնկրետ լուսանկարներ և տեսանյութեր"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Ընտրել այլ տարրեր"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Չընտրել ավելի շատ"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Չընտրել այլ լուսանկարներ"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Միևնույն է չթույլատրել"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Փակել"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Ցույց տալ ձայնային օգնականի ակտիվացման պատկերակը"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Ցույց տալ պատկերակը կարգավիճակի գոտում, երբ ձայնային օգնականի ակտիվացման համար օգտագործվում է խոսափողը"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել սարքի լուսանկարներն ու մուլտիմեդիա ֆայլերը"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր կոնտակտները"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի տեղադրության տվյալները"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Տեղադրության տվյալները հասանելի կլինեն հավելվածին, միայն երբ այն օգտագործելիս լինեք"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի տեղադրության տվյալները"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Հավելվածին անհրաժեշտ է ձեր գտնվելու վայրը հետագծելու թույլտվություն, նույնիսկ երբ դուք չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ"</annotation>"։"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Փոխե՞լ տեղադրության մասին տվյալների հասանելիությունը &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածի համար։"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Հավելվածին անհրաժեշտ է ձեր գտնվելու վայրը հետագծելու թույլտվություն, նույնիսկ երբ դուք չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ"</annotation>"։"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին գտնել մոտակա սարքերը, միանալ դրանց և որոշել դրանց հարաբերական դիրքավորումը։"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին գտնել մոտակա սարքերը, միանալ դրանց և որոշել դրանց հարաբերական դիրքավորումը։ Թույլատրելու համար անցեք "<annotation id="link">"կարգավորումներ։"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"«<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>» հավելվածի տեղորոշումը փոխե՞լ մոտավորից ճգշրիտի"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի մոտավոր տեղադրությունը"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Ճշգրիտ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Մոտավոր"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր օրացույցը:"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ուղարկել և դիտել SMS հաղորդագրություններ:"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել սարքում պահված լուսանկարները, մուլտիմեդիան և ֆայլերը"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի &lt;b&gt;լուսանկարները, տեսանյութերը, երաժշտությունը և աուդիո ֆայլերը&lt;/b&gt;"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի &lt;b&gt;նկարները, երգերը, տեսանյութերը, աուդիո ֆայլերը և մյուս ֆայլերը&lt;/b&gt;"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի երաժշտությունը և մյուս աուդիո ֆայլերը"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի լուսանկարներն ու տեսանյութերը"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի լուսանկարներն ու տեսանյութերը։"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել այս սարքի լուսանկարներն ու տեսանյութերը"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ձայնագրել"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Այս հավելվածը կկարողանա ձայնագրություններ անել միայն, երբ այն օգտագործելիս լինեք"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ձայնագրություններ անել։"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Այս հավելվածը հավանաբար կուզենա ձայնագրություններ անել նույնիսկ այն ժամանակ, երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Փոխե՞լ խոսափողի հասանելիության կարգավորումները &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածի համար։"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Այս հավելվածն ուզւոմ է ձայնագրություններ անել նույնիսկ այն ժամանակ, երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր ֆիզիկական ակտիվության տվյալները"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին լուսանկարել և տեսագրել"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Այս հավելվածը կկարողանա լուսանկարել և տեսագրել միայն, երբ այն օգտագործելիս լինեք"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին լուսանկարել և տեսագրել։"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Այս հավելվածը հավանաբար կուզենա լուսանկարել և տեսագրել նույնիսկ այն ժամանակ, երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Փոխե՞լ տեսախցիկի հասանելիության կարգավորումները &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածի համար։"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Այս հավելվածն ուզում է լուսանկարել և տեսագրել նույնիսկ այն ժամանակ, երբ չեք օգտվում դրանից։ "<annotation id="link">"Թույլտվությունը տրամադրեք այստեղ։"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին օգտագործել ձեր հեռախոսազանգերի մատյանները"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին կատարել հեռախոսազանգեր և կառավարել դրանք"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին սենսորից ստանալ ձեր կենսագործունեության հիմնական տվյալները:"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Եթե ուզում եք, որ այս հավելվածին հասանելի լինեն մարմնի սենսորների տվյալները, նույնիսկ երբ չեք օգտվում հավելվածից, "<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="auto_granted_permissions" msgid="6009452264824455892">"Կառավարվող թույլտվություններ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ծանուցումներ ուղարկել ձեզ"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Կառավարվող թույլտվություններ"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածն ունի տեղորոշման թույլտվություն"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Ձեր կազմակերպությունը հասանելի է դարձրել ձեր տեղադրությունը <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածին"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Այլ թույլտվություններ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Համակարգի կողմից օգտագործվող հավելվածներ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Միայն համակարգի հավելվածների կողմից օգտագործվող թույլտվություններ"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Այս հավելվածը կարող է երրորդ կողմերի հետ կիսվել տեղադրության տվյալներով"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Տվյալների փոխանցում և տեղորոշում"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Որտեղից են վերցվում տվյալներով կիսվելու մասին տեղեկությունները"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Մշակողն այս սարքի արտադրողին տրամադրել է տեղեկություններ, թե ինչպես է այս հավելվածը կիսվում տվյալներով։ Ժամանակի ընթացքում մշակողը կարող է թարմացնել այս տեղեկությունները։"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Մշակողը "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"-ին տրամադրել է տեղեկություններ, թե ինչպես է այս հավելվածը կիսվում տվյալներով։ Ժամանակի ընթացքում մշակողը կարող է թարմացնել այս տեղեկությունները։"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Տեղադրության տվյալներով կիսվելու նպատակները՝"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Տվյալներով կիսվելու եղանակները տարբեր են"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Տվյալների պաշտպանություն"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Տեղադրության տվյալները կարող են փոխանցվել"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Այս հավելվածը կարող է երրորդ կողմերի հետ կիսվել ձեր տեղադրության տվյալներով"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Չհաջողվեց բացել հղումը"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Տեղադրության մասին տվյալներով կիսվելու թույլտվության թարմացում"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Ստուգեք հավելվածների ցանկը, որոնք փոխել են ձեր տեղադրության տվյալներով կիսվելու եղանակը"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Այս հավելվածները փոխել են ձեր տեղադրության տվյալներով կիսվելու եղանակը։ Հնարավոր է, որ նշված հավելվածները նախկինում չեն կիսվել այդ տվյալներով կամ այժմ կիսվում են դրանցով գովազդային կամ մարքեթինգային նպատակներով։"</string>
diff --git a/PermissionController/res/values-in-v33/strings.xml b/PermissionController/res/values-in-v33/strings.xml
index f2215a915..b74e806df 100644
--- a/PermissionController/res/values-in-v33/strings.xml
+++ b/PermissionController/res/values-in-v33/strings.xml
@@ -19,7 +19,7 @@
<string name="role_dialer_request_description" msgid="6188305064871543419">"Aplikasi ini akan diizinkan untuk mengirim Notifikasi, dan akan diberi akses ke Kamera, Kontak, Mikrofon, Telepon, dan SMS Anda"</string>
<string name="role_sms_request_description" msgid="1506966389698625395">"Aplikasi ini akan diizinkan untuk mengirim Notifikasi, dan akan diberi akses ke Kamera, Kontak, File, Mikrofon, Telepon, dan SMS Anda"</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"Aplikasi yang memiliki izin ini dapat mengakses semua file di perangkat ini"</string>
- <string name="work_policy_title" msgid="832967780713677409">"Info kebijakan kerja Anda"</string>
+ <string name="work_policy_title" msgid="832967780713677409">"Info kebijakan profil kerja Anda"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"Setelan yang dikelola oleh admin IT"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Luaskan dan tampilkan daftar"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"Ciutkan daftar dan sembunyikan setelan"</string>
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Peringatan lainnya"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Peringatan yang ditutup"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Luaskan untuk melihat satu peringatan lain}other{Luaskan untuk melihat # peringatan lain}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Peringatan. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Tindakan selesai"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Periksa setelan yang dapat menambahkan perlindungan ke perangkat Anda"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Setelan cepat keamanan dan privasi"</string>
diff --git a/PermissionController/res/values-in-v34/strings.xml b/PermissionController/res/values-in-v34/strings.xml
index b26f77dc0..7e0c0a609 100644
--- a/PermissionController/res/values-in-v34/strings.xml
+++ b/PermissionController/res/values-in-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Keamanan &amp; privasi"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Kontrol"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Mengelola akses aplikasi ke data kesehatan"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Kelola akses aplikasi ke data kesehatan"</string>
<string name="location_settings" msgid="8863940440881290182">"Akses lokasi"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Untuk aplikasi dan layanan. Jika setelan ini nonaktif, data mikrofon mungkin tetap dibagikan saat Anda menelepon nomor darurat"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Untuk aplikasi dan layanan"</string>
diff --git a/PermissionController/res/values-in/strings.xml b/PermissionController/res/values-in/strings.xml
index 4540ba8e3..300036c3f 100644
--- a/PermissionController/res/values-in/strings.xml
+++ b/PermissionController/res/values-in/strings.xml
@@ -51,7 +51,7 @@
<string name="grant_dialog_button_allow" msgid="5314677880021102550">"Izinkan"</string>
<string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"Izinkan sepanjang waktu"</string>
<string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"Saat aplikasi digunakan"</string>
- <string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Ubah ke lokasi akurat"</string>
+ <string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Ubah ke lokasi presisi"</string>
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"Tetap gunakan perkiraan"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"Hanya kali ini"</string>
<string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"Izinkan sepanjang waktu"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Izinkan sepanjang waktu"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Izinkan saat apl digunakan"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Izinkan saat aplikasi digunakan"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Jangan izinkan"</string>
<string name="loading" msgid="4789365003890741082">"Memuat…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Semua izin"</string>
@@ -191,10 +191,10 @@
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"Selalu izinkan semua"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"Selalu tanya"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"Jangan izinkan"</string>
- <string name="precise_image_description" msgid="6349638632303619872">"Lokasi akurat"</string>
+ <string name="precise_image_description" msgid="6349638632303619872">"Lokasi presisi"</string>
<string name="approximate_image_description" msgid="938803699637069884">"Perkiraan lokasi"</string>
- <string name="app_permission_location_accuracy" msgid="7166912915040018669">"Gunakan lokasi akurat"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Saat lokasi akurat dinonaktifkan, aplikasi dapat mengakses perkiraan lokasi"</string>
+ <string name="app_permission_location_accuracy" msgid="7166912915040018669">"Gunakan lokasi presisi"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Saat lokasi presisi dinonaktifkan, aplikasi dapat mengakses perkiraan lokasi"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Izin <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Akses <xliff:g id="PERM">%1$s</xliff:g> untuk aplikasi ini"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Lihat semua izin <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -247,7 +247,7 @@
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"Ditolak / Tidak pernah mengakses"</string>
<string name="allowed_header" msgid="7769277978004790414">"Diizinkan"</string>
<string name="allowed_always_header" msgid="6455903312589013545">"Diizinkan sepanjang waktu"</string>
- <string name="allowed_foreground_header" msgid="6845655788447833353">"Hanya diizinkan saat digunakan"</string>
+ <string name="allowed_foreground_header" msgid="6845655788447833353">"Diizinkan hanya saat digunakan"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Hanya diizinkan akses ke media"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Diizinkan untuk mengelola semua file"</string>
<string name="ask_header" msgid="2633816846459944376">"Selalu tanya"</string>
@@ -399,7 +399,7 @@
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Layanan ini membagikan foto, media, dan notifikasi dari ponsel ke perangkat lain."</string>
<string name="role_notes_label" msgid="7451627001058089536">"Aplikasi catatan default"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Aplikasi catatan"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"Aplikasi yang memungkinkan Anda membuat catatan di perangkat"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"Aplikasi untuk membuat catatan di perangkat"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"catatan"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Default saat ini"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Jangan tanya lagi"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Tampilkan deteksi pemicu asisten"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Tampilkan ikon di status bar saat mikrofon digunakan untuk mengaktifkan asisten suara"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan media di perangkat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kontak?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi perangkat ini?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikasi ini hanya akan memiliki akses ke lokasi selagi Anda menggunakan aplikasi"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi perangkat ini?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Aplikasi ini mungkin ingin selalu mengakses lokasi, meski tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Ubah akses lokasi untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplikasi ini mungkin ingin selalu mengakses lokasi, meski tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan."</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar? "<annotation id="link">"Izinkan di setelan."</annotation></string>
- <string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Ubah akses lokasi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> dari perkiraan ke lokasi akurat?"</string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menemukan, terhubung ke, dan menentukan posisi relatif perangkat di sekitar? "<annotation id="link">"Izinkan di setelan."</annotation></string>
+ <string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Ubah akses lokasi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> dari perkiraan ke lokasi presisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses perkiraan lokasi perangkat ini?"</string>
- <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Akurat"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
+ <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Presisi"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Perkiraan"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kalender?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengirim dan melihat SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto, media, dan file di perangkat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses &lt;b&gt;foto, video, musik, dan audio&lt;/b&gt; di perangkat ini?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses &lt;b&gt;foto, video, musik, audio, dan file lainnya&lt;/b&gt; di perangkat ini?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses musik dan audio di perangkat ini?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan video di perangkat ini?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan video lainnya di perangkat ini?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merekam audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikasi hanya dapat merekam audio saat aplikasi sedang digunakan"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merekam audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Aplikasi ini mungkin ingin selalu merekam audio, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Ubah akses mikrofon untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Aplikasi ini ingin selalu merekam audio, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses aktivitas fisik Anda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merekam video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikasi hanya dapat mengambil gambar dan merekam video saat aplikasi sedang digunakan"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merekam video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Aplikasi ini mungkin ingin selalu mengambil gambar dan merekam video, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Ubah akses kamera untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Aplikasi ini ingin selalu mengambil gambar dan merekam video, meski aplikasi tidak sedang digunakan. "<annotation id="link">"Izinkan di setelan"</annotation>"."</string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Izin terkontrol"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Izin terkontrol"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> memiliki akses lokasi"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organisasi Anda mengizinkan <xliff:g id="APP_NAME">%1$s</xliff:g> mengakses lokasi Anda"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Izin lainnya"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Izin yang digunakan oleh sistem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Izin hanya digunakan oleh aplikasi sistem."</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"Untuk aplikasi dan layanan. Jika setelan ini nonaktif, data mikrofon mungkin tetap dibagikan saat Anda menelepon nomor darurat."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Lihat aplikasi dan layanan yang memiliki akses ke lokasi"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Tampilkan akses papan klip"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Menampilkan pesan saat aplikasi mengakses teks, gambar, atau konten lainnya yang telah Anda salin"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Tampilkan pesan saat aplikasi mengakses teks, gambar, atau konten lain yang telah Anda salin"</string>
<string name="show_password_title" msgid="2877269286984684659">"Tampilkan sandi"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Menampilkan karakter sejenak saat Anda mengetik"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Tampilkan karakter sejenak saat Anda mengetik"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Aplikasi ini menyatakan bahwa aplikasi mungkin membagikan data lokasi ke pihak ketiga"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Berbagi data dan lokasi"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Sumber info berbagi data"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Developer memberikan info kepada produsen perangkat ini tentang cara aplikasi ini berbagi data. Developer dapat memperbarui info ini dari waktu ke waktu."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Developer memberikan info kepada "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" tentang cara aplikasi ini berbagi data. Developer dapat memperbarui info ini dari waktu ke waktu."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Aplikasi ini mungkin membagikan data lokasi untuk:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Praktik berbagi data dapat berbeda-beda"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Keamanan data"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Data lokasi mungkin dibagikan"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Aplikasi ini menyatakan bahwa aplikasi mungkin membagikan data lokasi Anda kepada pihak ketiga"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Tidak dapat membuka link ini"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Pembaruan berbagi data untuk lokasi"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Tinjau aplikasi yang mengubah caranya berbagi data lokasi Anda"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Aplikasi ini telah mengubah caranya berbagi data lokasi Anda. Aplikasi mungkin sebelumnya tidak membagikan data, atau mungkin kini membagikan data untuk tujuan iklan atau pemasaran."</string>
diff --git a/PermissionController/res/values-is-v33/strings.xml b/PermissionController/res/values-is-v33/strings.xml
index 4fba44171..3f7695027 100644
--- a/PermissionController/res/values-is-v33/strings.xml
+++ b/PermissionController/res/values-is-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Fleiri tilkynningar"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Hunsaðar viðvaranir"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Stækka og sjá eina viðvörun í viðbót}one{Stækka og sjá # viðvörun í viðbót}other{Stækka og sjá # viðvaranir í viðbót}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Viðvörun. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Aðgerð lokið"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Skoðunarstillingar sem geta bætt öryggi tækisins þíns"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Flýtistillingar öryggis og persónuverndar"</string>
diff --git a/PermissionController/res/values-is/strings.xml b/PermissionController/res/values-is/strings.xml
index 83f737166..416931b69 100644
--- a/PermissionController/res/values-is/strings.xml
+++ b/PermissionController/res/values-is/strings.xml
@@ -124,7 +124,7 @@
<string name="current_permissions_category" msgid="4292990083585728880">"Núgildandi heimildir"</string>
<string name="message_staging" msgid="9110563899955511866">"Setur upp forrit…"</string>
<string name="app_name_unknown" msgid="1319665005754048952">"Óþekkt"</string>
- <string name="permission_usage_title" msgid="1568233336351734538">"Einkastjórnborð"</string>
+ <string name="permission_usage_title" msgid="1568233336351734538">"Persónuverndarstjórnborð"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Skoða hvaða forrit notuðu heimildir nýlega"</string>
<string name="permission_group_usage_title" msgid="2595013198075285173">"<xliff:g id="PERMGROUP">%1$s</xliff:g>: notkun"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Sjá aðrar heimildir"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Síðast opnað <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ef þú leyfir stjórnun allra skráa getur þetta forrit opnað, breytt og eytt öllum skrám í sameiginlegri geymslu í þessu tæki eða tengdum geymslutækjum. Þetta forrit getur opnað skrár án þess að spyrja þig."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Viltu gefa þessu forriti aðgang að skrám í tækinu eða tengdum geymslutækjum og leyfi til að breyta þeim og eyða? Þetta forrit getur opnað skrár án þess að spyrja þig."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Forrit með þessa heimild <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Forrit með þessa heimild mega <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Forrit með þessa heimild hafa aðgang að upplýsingum um hreyfingu þína, svo sem göngu, hjólreiðar, akstur, skrefafjölda og fleira"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Forrit með þessa heimild hafa aðgang að dagatalinu þínu"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Forrit með þessa heimild geta lesið og skrifað símtalaskrá síma"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Sýna virkjunarkennsl hjálpara"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Sýna tákn á stöðustiku þegar hljóðnemi er notaður til að ræsa raddaðstoð"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að myndum og efni í tækinu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að tengiliðunum þínum?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að staðsetningu þessa tækis?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Forritið hefur aðeins aðgang að staðsetningunni á meðan þú notar forritið"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að staðsetningu þessa tækis?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Þetta forrit gæti beðið um aðgang að staðsetningu þinni öllum stundum, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Viltu breyta aðgangi að staðsetningu fyrir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Þetta forrit vill fá aðgang að staðsetningu þinni öllum stundum, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að finna, tengjast við og ákvarða fjarlægð milli nálægra tækja?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að finna, tengjast við og ákvarða fjarlægð milli nálægra tækja? "<annotation id="link">"Þú getur leyft það í stillingunum."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Breyta aðgangi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> að staðsetningu úr áætlaðri í nákvæma?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að áætlaðri staðsetningu þessa tækis?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Nákvæm"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Áætluð"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að dagatalinu þínu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að senda og skoða SMS-skilaboð?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Viltu veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að myndum, efni og skrám í tækinu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að &lt;b&gt;myndum, myndskeiðum, tónlist og hljóði&lt;/b&gt; í þessu tæki?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að &lt;b&gt;myndum, myndskeiðum, tónlist, hljóði og öðrum skrám&lt;/b&gt; í þessu tæki?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að tónlist og hljóði í þessu tæki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að myndum og myndskeiðum í þessu tæki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Veita &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aðgang að fleiri myndum og myndskeiðum í þessu tæki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka upp hljóð?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Forritið mun aðeins geta tekið upp hljóð þegar þú ert að nota forritið"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka upp hljóð?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Þetta forrit gæti viljað taka upp hljóð hvenær sem er, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Viltu breyta aðgangi að hljóðnema fyrir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Þetta forrit vill taka upp hljóð hvenær sem er, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að fá aðgang að hreyfingu þinni?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka myndir og myndskeið?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Forritið mun aðeins geta tekið myndir og tekið upp myndskeið þegar þú ert að nota forritið"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka myndir og myndskeið?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Þetta forrit gæti viljað taka myndir og taka upp myndskeið hvenær sem er, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Viltu breyta aðgangi að myndavél fyrir &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Þetta forrit vill taka myndir og taka upp myndskeið hvenær sem er, jafnvel þegar þú ert ekki að nota forritið. "<annotation id="link">"Þú getur leyft það í stillingum."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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 um lífsmörk þín?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Til að veita þessu forriti samfelldan 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; áfram 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="auto_granted_permissions" msgid="6009452264824455892">"Stýrðar heimildir"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Stýrðar heimildir"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> er með staðsetningaraðgang"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Fyrirtækið þitt veitir <xliff:g id="APP_NAME">%1$s</xliff:g> aðgang að staðsetningu þinni"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Aðrar heimildir"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Heimildir sem kerfið notar"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Heimildir aðeins notaðar af kerfisforritum."</string>
@@ -581,7 +633,7 @@
<string name="privacy_controls_title" msgid="7605929972256835199">"Persónuverndarstillingar"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Aðgangur að myndavél"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Aðgangur að hljóðnema"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Fyrir forrit og þjónustu"</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Fyrir forrit og þjónustur"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Fyrir forrit og þjónustur. Þegar slökkt er á þessari stillingu verður hljóðnemagögnum þó hugsanlega deilt þegar þú hringir í neyðarnúmer."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Skoða forrit og þjónustur sem eru með aðgang að staðsetningu"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Sýna aðgang að klippiborði"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Þetta forrit gaf til kynna að það kunni að deila staðsetningargögnum með þriðju aðilum"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Gagnadeiling og staðsetning"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Hvaðan koma upplýsingar um gagnadeilingu"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Þróunaraðilinn veitti framleiðanda þessa tækis upplýsingar um hvernig þetta forrit deilir gögnum. Þróunaraðilinn kann að uppfæra þessar upplýsingar síðar."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Þróunaraðilinn veitti "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" upplýsingar um hvernig þetta forrit deilir gögnum. Þróunaraðilinn kann að uppfæra þessar upplýsingar síðar."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Forritið kann að deila staðsetningargögnum til að:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Gagnadeiling er mismunandi"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Gagnaöryggi"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Staðsetningargögnum kann að vera deilt"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Þetta forrit gaf til kynna að það kunni að deila staðsetningargögnum frá þér með þriðju aðilum"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Ekki er hægt að opna þennan tengil"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Uppfærslur um gagnadeilingu varðandi staðsetningu"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Yfirfarðu forrit sem breyttu því hvernig þau geta deilt staðsetningargögnunum þínum"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Deiling staðsetningargagna hefur breyst í þessum forritum. Þau hafa hugsanlega ekki deilt gögnunum áður eða deila þeim nú í auglýsinga- eða markaðssetningartilgangi."</string>
diff --git a/PermissionController/res/values-it/strings.xml b/PermissionController/res/values-it/strings.xml
index a122a5fa7..eee5c0c97 100644
--- a/PermissionController/res/values-it/strings.xml
+++ b/PermissionController/res/values-it/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Consenti sempre tutto"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Seleziona foto e video"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Seleziona più messaggi"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Non selezionare altri dati"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Non selezionare altro"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Non consentire comunque"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Ignora"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> di <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -245,13 +245,13 @@
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"Al momento rifiutata/Ultimo accesso: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"Accesso mai eseguito"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"Rifiutata/Accesso mai effettuato"</string>
- <string name="allowed_header" msgid="7769277978004790414">"Autorizzate"</string>
+ <string name="allowed_header" msgid="7769277978004790414">"Autorizzata"</string>
<string name="allowed_always_header" msgid="6455903312589013545">"Autorizzazione sempre concessa"</string>
<string name="allowed_foreground_header" msgid="6845655788447833353">"Autorizzazione concessa solo durante l\'uso"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"Autorizzate solo per contenuti multimediali"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"Autorizzate per gestire tutti i file"</string>
<string name="ask_header" msgid="2633816846459944376">"Chiedi ogni volta"</string>
- <string name="denied_header" msgid="903209608358177654">"Non autorizzate"</string>
+ <string name="denied_header" msgid="903209608358177654">"Non autorizzata"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"Visualizza altre app che possono accedere a tutti i file"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 giorno}many{# giorni}other{# giorni}}"</string>
<string name="hours" msgid="7302866489666950038">"{count,plural, =1{# ora}many{# ore}other{# ore}}"</string>
@@ -338,7 +338,7 @@
<string name="no_permissions_allowed" msgid="6081976856354669209">"Nessuna autorizzazione consentita"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"Nessuna autorizzazione rifiutata"</string>
<string name="no_apps_allowed" msgid="7718822655254468631">"Nessuna app autorizzata"</string>
- <string name="no_apps_allowed_full" msgid="8011716991498934104">"Nessuna app consentita per tutti i file"</string>
+ <string name="no_apps_allowed_full" msgid="8011716991498934104">"Nessuna app autorizzata per tutti i file"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Nessuna app autorizzata solo per i contenuti multimediali"</string>
<string name="no_apps_denied" msgid="7663435886986784743">"A nessuna app è stata negata l\'autorizzazione"</string>
<string name="car_permission_selected" msgid="180837028920791596">"Selezionato"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostra il rilevamento dell\'attivazione dell\'assistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostra l\'icona nella barra di stato quando viene usato il microfono per attivare l\'assistente vocale"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alle foto e ai contenuti multimediali sul tuo dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai tuoi contatti?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione di questo dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"L\'app avrà accesso alla posizione soltanto quando la usi"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione di questo dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Questa app potrebbe voler accedere sempre alla tua posizione, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vuoi cambiare l\'accesso alla posizione per l\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Questa app vorrebbe accedere sempre alla tua posizione, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni"</annotation>"."</string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi a dispositivi vicini, nonché stabilirne la posizione relativa?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi a dispositivi vicini, nonché stabilirne la posizione relativa? "<annotation id="link">"Consenti nelle impostazioni."</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi ai dispositivi vicini, e di stabilirne la posizione relativa?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di trovare e connettersi ai dispositivi vicini, e di stabilirne la posizione relativa? "<annotation id="link">"Consenti nelle impostazioni."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Modificare l\'accesso alla posizione di <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> da approssimativa a esatta?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla posizione approssimativa di questo dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Esatta"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Approssimativa"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere al tuo calendario?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di inviare e visualizzare SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere a foto, contenuti multimediali e file memorizzati sul dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere a &lt;b&gt;foto, video, musica e audio&lt;/b&gt; sul dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere a &lt;b&gt;foto, video, musica, audio e altri file&lt;/b&gt; sul dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere a musica e audio sul dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere a foto e video sul dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ad altri video e foto sul dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di registrare audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"L\'app potrà registrare audio soltanto quando la usi"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di registrare audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Questa app potrebbe voler registrare sempre audio, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vuoi cambiare l\'accesso al microfono per l\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Questa app vorrebbe registrare sempre audio, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere alla tua attività fisica?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di scattare foto e registrare video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"L\'app potrà scattare foto e registrare video soltanto quando la usi"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vuoi consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di scattare foto e registrare video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Questa app potrebbe voler scattare foto e registrare video sempre, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vuoi cambiare l\'accesso alla fotocamera per l\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Questa app vorrebbe scattare foto e registrare video sempre, anche quando non la usi. "<annotation id="link">"Consenti l\'accesso nelle impostazioni."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Questa app vuole accedere sempre ai dati dei sensori relativi ai tuoi 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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Per consentire a questa app di accedere sempre ai dati dei sensori del corpo, anche quando non la usi, "<annotation id="link">"vai alle impostazioni"</annotation>"."</string>
<string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Continuare a consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di accedere ai dati dei sensori del corpo mentre l\'app è in uso?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di inviarti notifiche?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Autorizzazioni controllate"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"L\'app <xliff:g id="APP_NAME">%1$s</xliff:g> ha accesso alla posizione"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"La tua organizzazione consente all\'app <xliff:g id="APP_NAME">%1$s</xliff:g> di accedere alla tua posizione"</string>
@@ -532,7 +586,7 @@
<string name="security_settings" msgid="3808106921175271317">"Impostazioni di sicurezza"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Autorizzazioni"</string>
<string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Sicurezza e privacy"</string>
- <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Verifica lo stato"</string>
+ <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Verifica stato"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Controlli per la privacy"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Altre impostazioni"</string>
<string name="camera_toggle_label_qs" msgid="3880261453066157285">"Accesso alla fotocamera"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Questa app ha dichiarato che potrebbe condividere dati sulla posizione con terze parti"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Condivisione dei dati e posizione"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Da dove provengono le informazioni sulla condivisione dei dati"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Lo sviluppatore ha fornito al produttore di questo dispositivo le informazioni sulla modalità di condivisione dei dati nell\'app. Lo sviluppatore potrebbe aggiornare queste informazioni nel tempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Lo sviluppatore ha fornito a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" informazioni sulla modalità di condivisione dei dati in questa app. Lo sviluppatore potrebbe aggiornare queste informazioni nel tempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"L\'app può condividere dati sulla posizione per:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"La condivisione dei dati varia"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Sicurezza dei dati"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Potrebbero essere condivisi dati sulla posizione"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Questa app ha dichiarato che potrebbe condividere i tuoi dati sulla posizione con terze parti"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Impossibile aprire questo link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Aggiornamenti relativi alla condivisione dei dati sulla posizione"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Controlla le app che hanno cambiato la modalità di condivisione dei tuoi dati sulla posizione"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Le app che seguono hanno cambiato la modalità di condivisione dei tuoi dati sulla posizione. Potrebbero non averli condivisi in precedenza oppure ora potrebbero condividerli per scopi pubblicitari o di marketing."</string>
diff --git a/PermissionController/res/values-iw-v33/strings.xml b/PermissionController/res/values-iw-v33/strings.xml
index 5525ff31f..b94c5f360 100644
--- a/PermissionController/res/values-iw-v33/strings.xml
+++ b/PermissionController/res/values-iw-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"התראות נוספות"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"התראות שנסגרו"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{הרחבה וצפייה בהתראה נוספת אחת}one{הרחבה וצפייה ב-# התראות נוספות}two{הרחבה וצפייה ב-# התראות נוספות}other{הרחבה וצפייה ב-# התראות נוספות}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"התראה. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"הפעולה הושלמה"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"בדיקת ההגדרות שיכולות לשפר את ההגנה על המכשיר"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"הגדרות מהירות של אבטחה ופרטיות"</string>
diff --git a/PermissionController/res/values-iw/strings.xml b/PermissionController/res/values-iw/strings.xml
index 020d318bb..bdf283b61 100644
--- a/PermissionController/res/values-iw/strings.xml
+++ b/PermissionController/res/values-iw/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"אין אישור בכל זאת"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"סגירה"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> מתוך <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"‏האם לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ‏<xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"‏תמיד לאשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לבצע <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"‏לאשר לאפליקציית &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ‏<xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"‏תמיד לאשר לאפליקציית &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"רק בזמן השימוש באפליקציה"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"תמיד"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"אין אישור ואין צורך לשאול שוב"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"הצגת הזיהוי של הפעלת האסיסטנט"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"הצגת הסמל בשורת הסטטוס כשהמיקרופון בשימוש, לצורך הפעלת האסיסטנט"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; גישה לתמונות ולמדיה במכשיר שלך?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לאנשי הקשר שלך?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה למיקום המכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"לאפליקציה תהיה גישה אל נתוני המיקום רק בזמן השימוש בה"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה למיקום המכשיר?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ייתכן שהאפליקציה הזו תרצה לקבל גישה לנתוני המיקום שלך כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"‏לשנות את הרשאת הגישה למיקום של &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"האפליקציה הזו רוצה לקבל גישה לנתוני המיקום שלך כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"‏לאשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לאתר מכשירים קרובים, להתחבר אליהם ולזהות את מיקומם היחסי?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"‏לאשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לאתר מכשירים קרובים, להתחבר אליהם ולזהות את מיקומם היחסי? "<annotation id="link">"יש לתת הרשאה בהגדרות"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"לשנות את הרשאת הגישה של <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ממיקום משוער למיקום מדויק?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה למיקום המשוער של המכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"מדויק"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"משוער"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה ליומן?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לשלוח הודעות SMS ולהציג אותן?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לתמונות, למדיה ולקבצים במכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"‏לתת לאפליקציה ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎‏ הרשאת גישה ‎&lt;b&gt;‎‏לתמונות, לסרטונים, למוזיקה ולאודיו‎&lt;/b&gt;‎‏ במכשיר?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"‏לתת לאפליקציה ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎‏ הרשאת גישה ‎&lt;b&gt;‎‏לתמונות, לסרטונים, למוזיקה, לאודיו ולקבצים אחרים‎&lt;/b&gt;‎‏ במכשיר?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"‏לתת לאפליקציה ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎‏ הרשאת גישה למוזיקה ולקובצי אודיו במכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"‏לתת לאפליקציה ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎‏ הרשאת גישה לתמונות ולסרטונים במכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‏לתת לאפליקציה ‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎‏ הרשאת גישה לתמונות ולסרטונים נוספים במכשיר?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏לאשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; להקליט אודיו?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"האפליקציה תוכל להקליט אודיו רק כאשר היא בשימוש"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה להקליט אודיו?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ייתכן שהאפליקציה הזו תרצה להקליט אודיו כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‏לשנות את הרשאת הגישה אל המיקרופון עבור &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"האפליקציה הזו רוצה להקליט אודיו כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"‏האם לאפשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; גישה לפעילות הגופנית שלך?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"‏לאשר לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לצלם תמונות וסרטונים?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"האפליקציה תוכל לצלם תמונות וסרטונים רק כאשר היא בשימוש"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לצלם תמונות וסרטונים?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ייתכן שהאפליקציה הזו תרצה לצלם תמונות וסרטונים כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"‏לשנות את הרשאת הגישה למצלמה של &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"האפליקציה זו רוצה לצלם תמונות ולהקליט סרטונים כל הזמן, גם כשהיא לא בשימוש. "<annotation id="link">"ניתן לאשר זאת בהגדרות."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה ליומני השיחות של הטלפון?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לבצע ולנהל שיחות טלפון?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאת גישה לנתוני חיישנים העוקבים אחר הסימנים החיוניים שלך?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"כדי לאפשר לאפליקציה הזו לגשת לנתונים של החיישנים הגופניים כל הזמן, גם כשהיא לא בשימוש, "<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="auto_granted_permissions" msgid="6009452264824455892">"הרשאות בבקרה"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לשלוח לך התראות?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"הרשאות בבקרה"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"לאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> יש הרשאת גישה למיקום"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"הארגון שלך מאפשר לאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> לגשת למיקום שלך"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"הרשאות אחרות"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"הרשאות שהמערכת משתמשת בהן"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"הרשאות שרק אפליקציות מערכת משתמשות בהן."</string>
@@ -548,8 +600,8 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"נעשה שימוש לאחרונה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="active_app_usage_qs" msgid="4063912870936464727">"בשימוש על ידי: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"נעשה שימוש לאחרונה על ידי: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"בשימוש על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"נעשה שימוש לאחרונה על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"בשימוש על ידי <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"האפליקציה הזו הצהירה שהיא עשויה לשתף נתוני מיקום עם צדדים שלישיים"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"שיתוף נתונים ומיקום"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"מאיפה מגיע המידע לגבי שיתוף הנתונים"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"מפתחי האפליקציה סיפקו מידע ליצרן המכשיר הזה על האופן שבו האפליקציה משתפת נתונים. המפתחים עשויים לעדכן את המידע הזה עם הזמן."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"‏המפתחים סיפקו מידע על האופן שבו האפליקציה משתפת נתונים כאן: "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". המפתחים עשויים לעדכן את המידע הזה עם הזמן."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"האפליקציה עשויה לשתף את נתוני המיקום למטרות הבאות:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"שיתוף הנתונים עשוי להיות שונה"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"אבטחת נתונים"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ייתכן שנתוני המיקום ישותפו"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"מפתחי האפליקציה הזו הצהירו שהאפליקציה עשויה לשתף את נתוני המיקום שלך עם צדדים שלישיים"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"לא ניתן לפתוח את הקישור הזה"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"עדכונים לגבי שיתוף נתוני מיקום"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"בדיקת אפליקציות שהדרך שלהן לשתף נתוני מיקום השתנתה"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"באפליקציות האלה, השתנה האופן שבו הן עשויות לשתף את נתוני המיקום שלך. יכול להיות שהן לא שיתפו את הנתונים האלה בעבר, או שעכשיו הן משתפות את נתוני המיקום לצורכי פרסום ושיווק."</string>
diff --git a/PermissionController/res/values-ja-v34/strings.xml b/PermissionController/res/values-ja-v34/strings.xml
index 5048fa031..1a27a1df1 100644
--- a/PermissionController/res/values-ja-v34/strings.xml
+++ b/PermissionController/res/values-ja-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"セキュリティとプライバシー"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"管理"</string>
<string name="health_connect_title" msgid="2132233890867430855">"ヘルスコネクト"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"健康に関するデータへのアプリのアクセス権を管理する"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"健康に関するデータへのアプリのアクセス権を管理します"</string>
<string name="location_settings" msgid="8863940440881290182">"位置情報へのアクセス"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"アプリとサービス。この設定が OFF の場合、緊急通報番号に発信したときは、マイクのデータが共有されることがあります。"</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"アプリとサービス"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"アプリとサービスによるアクセス。この設定が OFF の場合でも、緊急通報番号に発信したときは、マイクのデータが共有されることがあります"</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"アプリとサービスによるアクセス"</string>
</resources>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index 890ccd894..783d39fd2 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{今日}=1{1 日前}other{# 日前}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"アプリを無効にする"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"このアプリを無効にすると、Android などの他のアプリが正しく動作しなくなるおそれがあります。このアプリはデバイスにプリインストールされているため、削除できません。無効にするには、このアプリをオフにし、デバイスにアプリが表示されないようにします。"</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"権限マネージャー"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"権限マネージャ"</string>
<string name="never_ask_again" msgid="4728762438198560329">"今後表示しない"</string>
<string name="no_permissions" msgid="3881676756371148563">"権限がありません"</string>
<string name="additional_permissions" msgid="5801285469338873430">"その他の権限"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"アシスタントのトリガー検出を表示"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"マイクを使って音声アシスタントを有効にする場合にステータスバーにアイコンを表示する"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"デバイス内の写真やメディアへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"連絡先へのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"このデバイスの位置情報へのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"このアプリは、ユーザーがアプリを使用している間のみ位置情報にアクセスできます"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"このデバイスの位置情報へのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"このアプリは、未使用時も含め、常に位置情報にアクセスする可能性があります。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に対する位置情報へのアクセス許可を変更しますか?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"このアプリは、未使用時も含め、常に位置情報へのアクセスを試みます。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"付近のデバイスの検出、接続、相対位置の特定を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"付近のデバイスの検出、接続、相対位置の特定を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"<annotation id="link">"設定で許可してください。"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> の位置情報へのアクセスを「おおよそ」から「正確」に変更しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"このデバイスのおおよその位置情報へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"正確"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"おおよそ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"カレンダーへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS メッセージの送信と表示を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"デバイス内の写真、メディア、ファイルへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"このデバイス内の&lt;b&gt;写真、動画、音楽、音声&lt;/b&gt;へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"このデバイス内の&lt;b&gt;写真、動画、音楽、音声など&lt;/b&gt;へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"このデバイス内の音楽と音声へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"このデバイス内の写真と動画へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"このデバイス内の他の写真や動画へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"音声の録音を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"アプリは、ユーザーがアプリを使用している場合のみ音声を録音できます"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"音声の録音を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"このアプリは、いつでも(ユーザーがアプリを使用していない場合でも)音声を録音する可能性があります。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に対するマイクへのアクセス許可を変更しますか?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"このアプリは、いつでも(ユーザーがアプリを使用していない場合でも)音声を録音できる権限を求めています。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"身体活動データへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"写真と動画の撮影を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"アプリは、ユーザーがアプリを使用している場合のみ写真や動画を撮影できます"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"写真と動画の撮影を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"このアプリは、いつでも(ユーザーがアプリを使用していない場合でも)写真や動画を撮影する可能性があります。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に対するカメラへのアクセス許可を変更しますか?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"このアプリは、いつでも(ユーザーがアプリを使用していない場合でも)写真や動画を撮影できる権限を求めています。"<annotation id="link">"[設定] で許可してください。"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"通話履歴へのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"電話の発信と管理を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"バイタルサインに関するセンサーデータへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"アプリの未使用時も、常にボディセンサー データにアクセスすることをこのアプリに許可するには、"<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"通知の送信を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"権限は管理されています"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> は位置情報にアクセスできます"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"<xliff:g id="APP_NAME">%1$s</xliff:g> が位置情報にアクセスすることを組織が許可します"</string>
@@ -510,14 +564,14 @@
<string name="privdash_label_location" msgid="6882400763866489291">"位置情報"</string>
<string name="privdash_label_other" msgid="3710394147423236033">"その他"</string>
<string name="privdash_label_none" msgid="5991866260360484858">"なし"</string>
- <string name="privdash_label_24h" msgid="1512532123865375319">"24 時間\n以内"</string>
+ <string name="privdash_label_24h" msgid="1512532123865375319">"過去 \n24 時間"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"過去\n7 日間"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> は Android によって保護されています。あなたのデータはこのデバイス上で処理されるため、このアプリの権限の使用状況はステータスバーやプライバシー ダッシュボードには表示されません。"</string>
<string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> は Android によって保護されています。あなたのデータはこのデバイス上で処理されるため、このアプリの権限の使用状況はプライバシー ダッシュボードには表示されません。"</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"デバイスのカメラがブロックされています"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"デバイスのマイクがブロックされています"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"デバイスの位置情報が OFF です"</string>
- <string name="blocked_sensor_summary" msgid="4443707628305027375">"アプリとサービス"</string>
+ <string name="blocked_sensor_summary" msgid="4443707628305027375">"アプリとサービスによるアクセス"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"緊急通報番号に発信したときは、マイクのデータが引き続き共有されることがあります。"</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"変更"</string>
<string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"セキュリティとプライバシー"</string>
@@ -570,26 +624,27 @@
<string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"このアプリは最新バージョンの Android に対応していません。このアプリが音楽ファイルや音声ファイルにアクセスできない場合は、写真や動画へのアクセスも許可されません。"</string>
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"このアプリは最新バージョンの Android に対応していません。このアプリが写真や動画にアクセスできる場合は、音楽ファイルや音声ファイルへのアクセスも許可されます。"</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"このアプリは最新バージョンの Android に対応していません。このアプリが音楽ファイルや音声ファイルにアクセスできない場合は、写真や動画へのアクセスも許可されません。"</string>
- <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"バックグラウンドでの位置情報へのアクセス権があるアプリの確認"</string>
- <string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> は、閉じているときも、常に位置情報にアクセスできます"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"バックグラウンドでの位置情報へのアクセス権があるアプリの確認"</string>
- <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"このアプリは、閉じているときも、常に位置情報にアクセスできます。\n\n緊急情報アプリや緊急通報アプリのなかには、バックグラウンドで位置情報にアクセスできないと、意図したとおりに動作しないものがあります。"</string>
+ <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"バックグラウンドで位置情報にアクセスできるアプリを確認"</string>
+ <string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> は、開いていなくても常に位置情報にアクセスできます"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"バックグラウンドで位置情報にアクセスできるアプリを確認"</string>
+ <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"このアプリは、開いていなくても常に位置情報にアクセスできます。\n\n緊急情報アプリや緊急通報アプリのなかには、バックグラウンドで位置情報にアクセスできないと、意図したとおりに動作しないものもあります。"</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"アクセス権を変更しました"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"最近の位置情報の使用状況を確認"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"プライバシー管理"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"カメラへのアクセス"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"マイクへのアクセス"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"アプリとサービス"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"アプリとサービス。この設定が OFF の場合でも、緊急通報番号に発信するとマイクのデータが共有されることがあります。"</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"アプリとサービスによるアクセス"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"アプリとサービスによるアクセス。この設定が OFF の場合でも、緊急通報番号に発信したときは、マイクのデータが共有されることがあります。"</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"位置情報にアクセスできるアプリとサービスを確認"</string>
- <string name="show_clip_access_notification_title" msgid="5168467637351109096">"クリップボードへのアクセスを表示"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"クリップボードにコピーしたテキストや画像などにアプリがアクセスすると、メッセージで通知する"</string>
- <string name="show_password_title" msgid="2877269286984684659">"パスワードの表示"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"入力した文字を短い間表示する"</string>
+ <string name="show_clip_access_notification_title" msgid="5168467637351109096">"クリップボードへのアクセスを通知"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"クリップボードにコピーしたテキストや画像などにアプリがアクセスすると、メッセージが表示されます"</string>
+ <string name="show_password_title" msgid="2877269286984684659">"パスワードを表示"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"入力した文字を一瞬だけ表示します"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"このアプリは、位置情報をサードパーティと共有する可能性があります"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"データ共有と位置情報"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"データ共有情報の提供元"</string>
- <string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"デベロッパーは、このアプリがデータを共有する方法に関する情報を "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" に提供しています。この情報は時間が経つと更新される可能性があります。"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"デベロッパーは、このデバイスのメーカーに、このアプリによるデータ共有方法についての情報を提供しています。この情報は将来更新される場合があります。"</string>
+ <string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"デベロッパーは、このアプリによるデータ共有方法についての情報を "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" に提供しています。この情報は将来更新される場合があります。"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"このアプリが位置情報を共有する目的"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"さまざまなデータ共有方法"</string>
<string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"データの取り扱いは、アプリのバージョンや使用方法、ユーザーの年齢やお住まいの地域によって異なることがあります。"<annotation id="link">"データ共有の詳細"</annotation></string>
@@ -606,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"データ セーフティ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"位置情報が共有されることがあります"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"このアプリは位置情報をサードパーティと共有することがあります"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"このリンクを開くことができません"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"位置情報を共有する方法の更新"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"ユーザーの位置情報を共有する方法が変更されたアプリを確認できます"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"ユーザーの位置情報を共有する方法が変更されたアプリを確認します"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"これらのアプリで、ユーザーの位置情報を共有する方法が変更されました。以前は共有していなかったか、広告またはマーケティングの目的で共有されるようになった可能性があります。"</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"これらのアプリのデベロッパーは、データの共有方法に関する情報をアプリストアに提供しています。この情報は時間が経つと更新される可能性があります。\n\nデータの共有方法は、アプリのバージョンや使用方法、ユーザーの年齢やお住まいの地域によって異なることがあります。"</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"データ共有の詳細"</string>
diff --git a/PermissionController/res/values-ka-v33/strings.xml b/PermissionController/res/values-ka-v33/strings.xml
index 5e668e51d..f92c9ebe8 100644
--- a/PermissionController/res/values-ka-v33/strings.xml
+++ b/PermissionController/res/values-ka-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"სხვა გაფრთხილებები"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"დახურული გაფრთხილებები"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{გააფართოვეთ და ნახეთ კიდევ ერთი გაფრთხილება}other{გააფართოვეთ და იხილეთ კიდევ # გაფრთხილება}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"გაფრთხილება. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"მოქმედება დასრულებულია"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"შეამოწმეთ პარამეტრები თქვენი მოწყობილობის უსაფრთხოების გასაძლიერებლად"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"უსაფრთხოებისა და კონფიდენციალურობის სწრაფი პარამეტრები"</string>
diff --git a/PermissionController/res/values-ka/strings.xml b/PermissionController/res/values-ka/strings.xml
index 3de674f1c..858922a41 100644
--- a/PermissionController/res/values-ka/strings.xml
+++ b/PermissionController/res/values-ka/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"ყოველთვის ყველას დაშვება"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"ფოტოებისა და ვიდეოების არჩევა"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"მეტის არჩევა"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"ნუ აირჩევთ მეტს"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"მეტის აღარ არჩევა"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"მაინც არ დაიშვას"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"დახურვა"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>-დან"</string>
@@ -455,53 +455,78 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"ასისტენტის გაშვების ხატულის ჩვენება"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"მიკროფონის მეშვეობით ხმოვანი ასისტენტის გააქტიურებისას სტატუსის ზოლში ხატულის ჩვენება"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენს მოწყობილობაზე არსებულ ფოტოებსა და მედია-კონტენტზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა ფოტოებსა და მედიაზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; თქვენს კონტაქტებზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენს კონტაქტებზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; ამ მოწყობილობის მდებარეობაზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენი &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის&lt;/b&gt; მდებარეობაზე?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ამ აპს მდებარეობაზე წვდომა მხოლოდ მაშინ ექნება, როცა თქვენ მას გამოიყენებთ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; ამ მოწყობილობის მდებარეობაზე წვდომის ნებართვა?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენი &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>-ის მდებარეობაზე?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"აპი ითხოვს თქვენს მდებარეობაზე წვდომას ნებისმიერ დროს, მაშინაც კი, როცა მას არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"გსურთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის&lt;/b&gt; მდებარეობაზე წვდომის შეცვლა?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"შეცვლით მდებარეობაზე წვდომას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპისთვის თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"აპი ითხოვს თქვენს მდებარეობაზე წვდომას ნებისმიერ დროს, მაშინაც კი, როცა მას არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"მიეცეს საშუალება &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს იპოვოს ახლომახლო მოწყობილობები, დაუკავშირდეს მათ და დაადგინოს პოზიცია მათ მიმართ?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, იპოვოს, დაუკავშირდეს და დაადგინოს ახლომახლო მოწყობილობების შედარებითი პოზიცია თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"მიეცეს საშუალება &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს იპოვოს ახლომახლო მოწყობილობები, დაუკავშირდეს მათ და დაადგინოს პოზიცია მათ მიმართ? "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"შეიცვალოს <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>-ის მდებარეობაზე წვდომა მიახლოებითის მაგიერ ზუსტით?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"შეცვლით <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>-ის მდებარეობის (მიახლოებითს ზუსტით) წვდომას თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; ამ მოწყობილობის მიახლოებით მდებარეობაზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენი &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ის მიახლოებით მდებარეობაზე?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ზუსტი"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"მიახლოებითი"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; თქვენს კალენდარზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენს კალენდარზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; SMS-შეტყობინებათა გაგზავნის და ნახვის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, გაგზავნოს და ნახოს SMS შეტყობინებები თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; თქვენს მოწყობილობაზე არსებულ ფოტოებზე, მედია-კონტენტზე და ფაილებზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა ფოტოებზე, მედიასა და ფაილებზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"მიანიჭებთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს წვდომას ამ მოწყ. &lt;b&gt;ფოტოებზე, ვიდეოებზე, მუსიკასა და აუდიოფაილებზე&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"მიანიჭებთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ის წვდომას თქვენი მოწყ. &lt;b&gt;ფოტოებზე, ვიდეოებზე, მუსიკაზე, აუდიო და სხვა &lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"მიანიჭებთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს წვდომას თქვენი მოწყობილობის მუსიკასა და აუდიოფაილებზე?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა მუსიკასა და აუდიოზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"მიანიჭებთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს წვდომას თქვენი მოწყობილობის ფოტოებსა და ვიდეოებზე?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"მიანიჭეთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს წვდომა თქვენი მოწყობილობის ფოტოებსა და ვიდეოებზე?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა ფოტოებსა და ვიდეოებზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"მიენიჭოს &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს წვდომა თქვენი მოწყობილობის ფოტოებსა და ვიდეოებზე?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა მეტ ფოტოსა და ვიდეოზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; აუდიოს ჩაწერის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჩაწეროს აუდიო თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ეს აპი აუდიოს ჩაწერას მხოლოდ მაშინ შეძლებს, როცა მას იყენებთ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; აუდიოს ჩაწერის ნებართვა?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჩაწეროს აუდიო თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ამ აპს შეუძლია აუდიოს ჩაწერა ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"გსურთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის&lt;/b&gt; მიკროფონის წვდომის შეცვლა?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"შეცვლით მიკროფონზე წვდომას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპისთვის თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ეს აპი აუდიოს ჩაწერს ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. "<annotation id="link">"Allow in settings."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენს ფიზიკურ აქტივობაზე წვდომის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენს ფიზიკურ აქტივობაზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; სურათების გადაღების და ვიდეოების ჩაწერის ნებართვა?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, გადაიღოს სურათები და ჩაწეროს ვიდეო თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ეს აპი სურათების გადაღებას და ვიდეოს ჩაწერას მხოლოდ მაშინ შეძლებს, როცა მას იყენებთ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; სურათების გადაღების და ვიდეოების ჩაწერის ნებართვა?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, გადაიღოს სურათები და ჩაწეროს ვიდეო თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ამ აპს შეუძლია სურათების გადაღება და ვიდეოს ჩაწერა ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"გსურთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ისთვის&lt;/b&gt; კამერის წვდომის შეცვლა?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"შეცვლით კამერაზე წვდომას &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპისთვის თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ეს აპი სურათების გადაიღებს და ვიდეოს ჩაწერს ნებისმიერ დროს, მაშინაც კი, როცა აპს არ იყენებთ. "<annotation id="link">"დაუშვით პარამეტრებიდან."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა თქვენი ტელ-ის ზარების ჟურნალზე &lt;b&gt;<xliff:g id="DEVICE">%2$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_device_aware_phone" msgid="4389610977195521813">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, განახორციელოს და მართოს სატელეფ. ზარები თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა სენსორის მონაცემებზე (სასიცოცხლო მაჩვენებლები) &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, ჰქონდეს წვდომა სენსორის მონაცემებზე (სასიცოცხლო მაჩვენებლები) &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ამ აპისთვის სხეულის სენსორების მონაცემებზე მუდმივი წვდომის მისანიჭებლად (მაშინაც კი, როცა აპს არ იყენებთ), "<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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, გამოყენებისას ჰქონდეს წვდომა სხეულის სენსორების მონაცემებზე თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"ნებას დართავთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; აპს, გამოგიგზავნოთ შეტყობინებები თქვენს &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"კონტროლირებული ნებართვები"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
- <skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
- <skip />
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს მდებარეობაზე წვდომა აქვს"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"თქვენი ორგანიზაცია ნებას რთავს <xliff:g id="APP_NAME">%1$s</xliff:g>-ს, წვდომა ჰქონდეს თქვენ მდებარეობაზე"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"სხვა ნებართვები"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"ნებართვები, რომლებსაც სისტემა იყენებს"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"ნებართვები, რომლებსაც მხოლოდ სისტემის აპლიკაციები იყენებს."</string>
@@ -591,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ამ აპის თანახმად, მან შესაძლოა გაუზიაროს მდებარეობის მონაცემები მესამე მხარეს"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"მონაცემთა გაზიარება და მდებარეობა"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"საიდან მოდის მონაცემთა გაზიარების ინფორმაცია"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"დეველოპერმა მოცემული მოწყობილობის მწარმოებელს მიაწოდა ინფორმაცია ამ აპის მიერ ინფორმაციის გაზიარების შესახებ. დეველოპერმა, შესაძლოა, დროთა განმავლობაში განაახლოს ეს ინფორმაცია."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"დეველოპერმა ინფორმაცია დაურთო "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"-ს ამ აპის მიერ ინფორმაციის გაზიარების შესახებ. დეველოპერმა შესაძლოა, დროთა განმავლობაში განაახლოს ეს ინფორმაცია."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"აპმა შესაძლოა, გაუზიაროს მდებარეობის მონაცემები:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"მონაცემთა გაზიარება განსხვავდება"</string>
@@ -608,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"მონაცემთა უსაფრთხოება"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"მდებარეობის მონაცემები შესაძლოა გაზიარებულია"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ამ აპის თანახმად, მან შესაძლოა გაუზიაროს თქვენი მდებარეობის მონაცემები მესამე მხარეს"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ამ ბმულის გახსნა შეუძლებელია"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"მონაცემების გაზიარ. განახლებები მდებარეობისთვის"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"გადახედეთ აპებს, რომლებშიც შეიცვალა თქვენი მდებარეობის მონაცემების გაზიარების მეთოდი"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ამ აპებმა შეცვალა თქვენი მდებარეობის მონაცემების გაზიარების გზები. შესაძლოა, ისინი ადრე არ გაუზიარებიათ, ან გაზიარდა ახლა რეკლამირების ან მარკეტინგული მიზნით."</string>
diff --git a/PermissionController/res/values-kk-v33/strings.xml b/PermissionController/res/values-kk-v33/strings.xml
index 06da81337..9538c1503 100644
--- a/PermissionController/res/values-kk-v33/strings.xml
+++ b/PermissionController/res/values-kk-v33/strings.xml
@@ -30,10 +30,9 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Басқа хабарландырулар"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Жабылған хабарландырулар"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Тағы бір хабарландыруды жаю және көру}other{Тағы # хабарландыруды жаю және көру}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Ескерту. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Әрекет аяқталды."</string>
- <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Құрығыңыздың қауіпсіздігін арттыруы ықтимал параметрлерді тексеріңіз."</string>
+ <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Құрығыңыздың қауіпсіздігін арттыратын параметрлерді тексеріңіз."</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Қауіпсіздік және құпиялық жылдам параметрлері"</string>
<string name="safety_center_qs_close_button" msgid="1352313308176244599">"Жабу"</string>
<string name="safety_center_qs_expand_action" msgid="2193190557696484169">"Опцияларды жаю және көрсету"</string>
@@ -41,7 +40,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Ауыстырғыш. <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g>. <xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Ауыстырғыш"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Ашу"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Параметрлерді қарап шығу"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Параметрлерді тексеру"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Параметрлер"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Ақпарат"</string>
</resources>
diff --git a/PermissionController/res/values-kk-v34/strings.xml b/PermissionController/res/values-kk-v34/strings.xml
index 45ed52f2f..002624b5a 100644
--- a/PermissionController/res/values-kk-v34/strings.xml
+++ b/PermissionController/res/values-kk-v34/strings.xml
@@ -23,5 +23,5 @@
<string name="health_connect_summary" msgid="815473513776882296">"Қолданбаның денсаулық деректерін пайдалану рұқсатын басқару"</string>
<string name="location_settings" msgid="8863940440881290182">"Локацияны пайдалану рұқсаты"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Қолданбалар мен қызметтерге арналған. Бұл параметр өшірілсе де, құтқару қызметінің нөміріне қоңырау шалғанда, микрофон деректері жіберілуі мүмкін."</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"Қолданбалар мен қызметтер үшін"</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"Қолданбалар мен қызметтерге арналған."</string>
</resources>
diff --git a/PermissionController/res/values-kk/strings.xml b/PermissionController/res/values-kk/strings.xml
index 862cb1c12..4a1c5ec34 100644
--- a/PermissionController/res/values-kk/strings.xml
+++ b/PermissionController/res/values-kk/strings.xml
@@ -41,7 +41,7 @@
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Жабу"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына <xliff:g id="ACTION">%2$s</xliff:g> рұқсатын беру керек пе?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы үшін <xliff:g id="ACTION">%2$s</xliff:g> әрекетіне әрқашан рұқсат етілсін бе?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына <xliff:g id="ACTION">%2$s</xliff:g> рұқсаты әрдайым берілсін бе?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Қолданба пайдаланылғанда ғана"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Әрқашан"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Рұқсат бермеу және қайта сұрамау"</string>
@@ -163,7 +163,7 @@
<string name="permission_usage_bar_chart_title_last_minute" msgid="820450867183487607">"Рұқсаттың соңғы 1 минутта пайдаланылуы"</string>
<string name="permission_usage_preference_summary_not_used_in_past_n_days" msgid="4771868094611359651">"{count,plural, =1{Соңғы # күнде пайдаланылмады.}other{Соңғы # күнде пайдаланылмады.}}"</string>
<string name="permission_usage_preference_summary_not_used_in_past_n_hours" msgid="3828973177433435742">"{count,plural, =1{Соңғы # сағатта пайдаланылмады.}other{Соңғы # сағатта пайдаланылмады.}}"</string>
- <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{1 қолданба пайдаланды}other{# қолданба пайдаланды}}"</string>
+ <string name="permission_usage_preference_label" msgid="8343167938128676378">"{count,plural, =1{1 қолданба пайдаланды.}other{# қолданба пайдаланды.}}"</string>
<string name="permission_usage_view_details" msgid="6675335735468752787">"Барлығын бақылау тақтасынан көру"</string>
<string name="app_permission_usage_filter_label" msgid="7182861154638631550">"Сүзгі шарты: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_usage_remove_filter" msgid="2926157607436428207">"Сүзгіні өшіру"</string>
@@ -258,12 +258,12 @@
<string name="minutes" msgid="4868414855445375753">"{count,plural, =1{# минут}other{# минут}}"</string>
<string name="seconds" msgid="5893958182059842734">"{count,plural, =1{# секунд}other{# секунд}}"</string>
<string name="permission_reminders" msgid="6528257957664832636">"Рұқсат туралы еске салғыштар"</string>
- <string name="auto_revoke_permission_reminder_notification_title_one" msgid="6690347469376854137">"1 пайдаланылмайтын қолданба"</string>
- <string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> пайдаланылмайтын қолданба бар"</string>
+ <string name="auto_revoke_permission_reminder_notification_title_one" msgid="6690347469376854137">"1 қолданба пайдаланылмайды"</string>
+ <string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> қолданба пайдаланылмайды бар"</string>
<string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"Құпиялықты қорғау үшін рұқсаттар өшірілді. Көру үшін түртіңіз."</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"Пайдаланылмайтын қолданбалар үшін рұқсаттар өшірілді"</string>
<string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"Кейбір қолданбалар бірнеше ай бойы пайдаланылмаған. Көру үшін түртіңіз."</string>
- <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# пайдаланылмайтын қолданба}other{# пайдаланылмайтын қолданба}}"</string>
+ <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# қолданба пайдаланылмайды}other{# қолданба пайдаланылмайды}}"</string>
<string name="unused_apps_notification_content" msgid="9195026773244581246">"Рұқсаттар мен уақытша файлдар өшірілді және хабарландырулар тоқтатылды. Көру үшін түртіңіз."</string>
<string name="unused_apps_safety_center_card_title" msgid="5638409355530099149">"Рұқсаттары өшірілген қолданбаларды қарап шығыңыз"</string>
<string name="unused_apps_safety_center_card_content" msgid="1088557243627427820">"Біраз уақыттан бері пайдаланылмаған қолданбалар бойынша рұқсаттар мен уақытша файлдар өшірілді және хабарландырулар тоқтатылды."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Көмекшінің іске қосылғанын анықтауды көрсету"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Микрофон арқылы дауыс көмекшісін іске қосқанда, күй жолағында белгішені көрсету"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына құрылғыдағы суреттерді, медиафайлдарды пайдалануға рұқсат берілсін бе?"</string>
- <string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына контактілерге кіруге рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
+ <string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына контактілерді пайдалануға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғының локациясын пайдалануға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Қолданбаны пайдалану кезінде ғана оған геодеректеріңізді көруге рұқсат етіледі."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғының локациясын пайдалануға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Қолданбаны пайдаланбасаңыз да, ол үнемі геодеректеріңізді пайдаланғысы келуі мүмкін. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына геодеректі пайдалануға рұқсат етілсін бе?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Қолданбаны пайдаланбасаңыз да, ол үнемі геодеректеріңізді пайдаланғысы келеді. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына маңайдағы құрылғыларды табуға, олармен байланысуға және олардың орналасуын анықтауға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына маңайдағы құрылғыларды табуға, олармен байланысуға және олардың орналасуын анықтауға рұқсат берілсін бе? "<annotation id="link">"Параметрлерден рұқсат бере аласыз."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> қолданбасының болжалды емес, нақты локацияны пайдалануына рұқсат беру керек пе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғының болжалды орнын пайдалануға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Нақты"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Болжалды"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына күнтізбеге кіруге рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына SMS хабарларын жіберуге және көруге рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына құрылғыдағы суреттерге, медиафайлдарға және басқа файлдарға кіруге рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғыдағы &lt;b&gt;фотосурет, бейне, музыка мен аудионы&lt;/b&gt; пайдалану рұқсаты берілсін бе?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғыдағы &lt;b&gt;фотосурет, бейне, музыка, аудио мен басқа файлдарды&lt;/b&gt; пайдалану рұқсаты берілсін бе?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғыдағы музыка мен аудионы пайдалану рұқсаты берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына осы құрылғыдағы фотосурет пен бейнені пайдалану рұқсаты берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы осы құрылғыдағы басқа фотосуреттер мен бейнелерді пайдалансын ба?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына дыбыс жазуға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Қолданба тек жұмыс кезінде ғана аудиомазмұн жаза алады."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына аудиомазмұн жазуға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Қолданбаны пайдаланбасаңыз да, ол кез келген уақытта бейнелерді жаза алады. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына микрофонды пайдалануға рұқсат етілсін бе?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Қолданбаны пайдаланбасаңыз да, ол кез келген уақытта аудиомазмұн жазғысы келеді. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына қимыл-қозғалыс дерегін алуға рұқсат етілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына суретке түсіруге және бейне жазуға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Қолданба тек жұмыс кезінде ғана суретке түсіріп, бейне жаза алады."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына суретке түсіруге және бейне жазуға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Қолданбаны пайдаланбасаңыз да, ол кез келген уақытта суретке түсіріп, бейнелер жаза алады. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына камераны пайдалануға рұқсат етілсін бе?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Қолданбаны пайдаланбасаңыз да, ол кез келген уақытта суретке түсіріп, бейне жазғысы келеді. "<annotation id="link">"Параметрлерден рұқсат беріңіз."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына телефонның қоңыраулар журналына кіруге рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына қоңырау шалуға және қоңырауларды басқаруға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына негізгі физиологиялық көрсеткіштерді көрсететін сенсорлық деректерді пайдалануға рұқсат берілсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Бұл қолданбаға кез келген уақытта (ол пайдаланылмаған кезде де) дене датчигінен алынған деректі пайдалануға рұқсат беру үшін "<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="auto_granted_permissions" msgid="6009452264824455892">"Басқарылатын рұқсаттар"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасы хабарландыру жіберсін бе?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Басқарылатын рұқсаттар"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы локацияны пайдаланады"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Ұйымыңыз <xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасына локацияңызды пайдалануға рұқсат береді."</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Басқа рұқсаттар"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Жүйе пайдаланатын рұқсаттар"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Тек жүйе қолданбалары пайдаланатын рұқсаттар."</string>
@@ -516,8 +568,8 @@
<string name="privdash_label_7d" msgid="5645301995348656931">"Соңғы\n7 күн"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын Android қорғайды. Деректеріңіз осы құрылғыда өңделетіндіктен, бұл қолданба рұқсатының пайдаланылуы күй жолағында немесе құпиялық тақтасында көрсетілмейді."</string>
<string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасын Android қорғайды. Деректеріңіз осы құрылғыда өңделетіндіктен, бұл қолданба рұқсатының пайдаланылуы құпиялық тақтасында көрсетілмейді."</string>
- <string name="blocked_camera_title" msgid="1128510551791284384">"Құрылғы камерасы бөгелген"</string>
- <string name="blocked_microphone_title" msgid="1631517143648232585">"Құрылғы микрофоны бөгелген"</string>
+ <string name="blocked_camera_title" msgid="1128510551791284384">"Құрылғы камерасы блокталған"</string>
+ <string name="blocked_microphone_title" msgid="1631517143648232585">"Құрылғы микрофоны блокталған"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"Құрылғы геодерегі өшірулі"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"Қолданбалар мен қызметтер үшін"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Құтқару қызметінің нөміріне қоңырау шалу кезінде микрофон деректері әлі бөлісіліп жатуы мүмкін."</string>
@@ -548,11 +600,11 @@
<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>
+ <string name="active_app_usage_qs" msgid="4063912870936464727">"<xliff:g id="APP_NAME">%1$s</xliff:g> пайдаланып жатыр."</string>
<string name="recent_app_usage_qs" msgid="6650259601306212327">"Соңғы рет <xliff:g id="APP_NAME">%1$s</xliff:g> пайдаланды."</string>
- <string name="active_app_usage_1_qs" msgid="4325136375823357052">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) пайдалануда."</string>
+ <string name="active_app_usage_1_qs" msgid="4325136375823357052">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) пайдаланып жатыр."</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"Соңғы рет <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) пайдаланды."</string>
- <string name="active_app_usage_2_qs" msgid="6107866785243565283">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) пайдалануда."</string>
+ <string name="active_app_usage_2_qs" msgid="6107866785243565283">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) пайдаланып жатыр."</string>
<string name="recent_app_usage_2_qs" msgid="3591205954235694403">"Соңғы рет <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) пайдаланды."</string>
<string name="media_confirm_dialog_positive_button" msgid="9020793594051526399">"Растау"</string>
<string name="media_confirm_dialog_negative_button" msgid="226987376924861785">"Артқа"</string>
@@ -581,7 +633,7 @@
<string name="privacy_controls_title" msgid="7605929972256835199">"Құпиялық параметрлері"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Камераны пайдалану"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Микрофонды пайдалану"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Қолданбалар мен қызметтер үшін"</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Қолданбалар мен қызметтерге арналған."</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Қолданбалар мен қызметтерге арналған. Бұл параметр өшірілсе де, құтқару қызметінің нөміріне қоңырау шалғанда, микрофон деректері жіберілуі мүмкін."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Локацияны пайдалана алатын қолданбалар мен қызметтерді көру"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Буфер пайдаланылғанын көрсету"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Бұл қолданба геодеректі үшінші тараптармен бөлісуі мүмкін екенін мәлімдеді."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Деректерді бөлісу және локация"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Деректерді бөлісу туралы ақпарат қайдан алынады?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Әзірлеуші осы құрылғының өндірушісіне қолданбаның деректерді қалай бөлісетіні туралы ақпарат берді. Әзірлеуші бұл ақпаратты уақыт өте келе жаңарта алады."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Әзірлеуші "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" қызметінде бұл қолданбаның деректерді бөлісу жолы туралы ақпарат берді. Ол бұл ақпаратты уақыт өте келе жаңарта алады."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Қолданбаның локация деректерін бөлісу мақсаттары:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Деректерді бөлісу әртүрлі болады"</string>
@@ -608,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Дерек қауіпсіздігі"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Локация деректері жіберілуі мүмкін."</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Бұл қолданба локация деректеріңізді үшінші тараптармен бөлісе алатынын мәлімдеді."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Бұл сілтемені ашу мүмкін емес"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Локация деректерін бөлісу жаңартулары"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"Локация деректеріңізді бөлісу жолын өзгерткен қолданбаларды қарап шығыңыз."</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"Локация деректеріңізді бөлісу жолын өзгерткен қолданбаларды тексеру"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Осы қолданбалар локация деректерін бөлісу жолын өзгертті. Олар деректерді бұрын бөліспей, енді жарнамалау не маркетинг үшін бөлісуі мүмкін."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Бұл қолданбалардың әзірлеушілері App Store дүкенінде өздерінің деректерді бөлісу тәртібі туралы ақпарат берді. Олар уақыт өте келе оны жаңарта алады.\n\nДеректерді бөлісу тәртібі қолданбаңыздың нұсқасына, пайдаланылуына, аймағыңыз бен жасыңызға байланысты әртүрлі болуы мүмкін."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Деректерді бөлісу туралы ақпарат"</string>
diff --git a/PermissionController/res/values-km/strings.xml b/PermissionController/res/values-km/strings.xml
index 81d05b141..006441908 100644
--- a/PermissionController/res/values-km/strings.xml
+++ b/PermissionController/res/values-km/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"មិនអីទេ មិនអនុញ្ញាត"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"ច្រានចោល"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> ក្នុងចំណោម <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> មែនទេ?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> ជានិច្ចមែនទេ?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>​មែនទេ?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>​ជានិច្ចមែនទេ?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"ខណៈពេលប្រើ​កម្មវិធីតែប៉ុណ្ណោះ"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"ជានិច្ច"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"មិនអនុញ្ញាត និងកុំសួរម្ដងទៀត"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"បង្ហាញការ​ចាប់សញ្ញា​របស់ជំនួយការ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"បង្ហាញ​រូបតំណាង​នៅក្នុង​របារស្ថានភាព នៅពេលប្រើប្រាស់​មីក្រូហ្វូន​ ដើម្បី​បើកដំណើរការ​ជំនួយការសំឡេង"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​រូបថត និង​មេឌៀ​នៅលើ​ឧបករណ៍​របស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទំនាក់ទំនង​របស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទីតាំងរបស់​ឧបករណ៍នេះ​ដែរទេ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"កម្មវិធីនេះ​នឹងមាន​សិទ្ធិ​ចូលប្រើ​ទីតាំង នៅពេល​អ្នកកំពុង​ប្រើ​កម្មវិធីនេះ​តែ​ប៉ុណ្ណោះ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទីតាំងរបស់​ឧបករណ៍នេះ​ដែរទេ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"កម្មវិធីនេះ​ប្រហែលជា​ចង់ចូលប្រើ​ទីតាំង​របស់អ្នក​គ្រប់ពេល ទោះបីជា​អ្នកមិនកំពុងប្រើ​កម្មវិធីនេះ​ក៏ដោយ។ "<annotation id="link">"អនុញ្ញាត​នៅក្នុងការកំណត់។"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"ប្ដូរសិទ្ធិ​ចូលប្រើ​ទីតាំង​សម្រាប់ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ដែរទេ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"កម្មវិធីនេះ​ចង់ចូលប្រើ​ទីតាំង​របស់អ្នក​គ្រប់ពេល ទោះបីជា​អ្នកមិនកំពុងប្រើ​កម្មវិធីនេះ​ក៏ដោយ។ "<annotation id="link">"អនុញ្ញាត​នៅក្នុងការកំណត់។"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ស្វែងរក ភ្ជាប់ទៅ និងកំណត់ទីតាំង​ដែលពាក់ព័ន្ធនៃ​ឧបករណ៍ដែលនៅជិតឬ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ស្វែងរក ភ្ជាប់ទៅ និងកំណត់ទីតាំង​ដែលពាក់ព័ន្ធនៃ​ឧបករណ៍ដែលនៅជិតឬ? "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"ផ្លាស់ប្ដូរ​ការចូលប្រើ​ទីតាំងរបស់ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ពីទីតាំងប្រហាក់ប្រហែល​ទៅជាក់លាក់ឬ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទីតាំងប្រហាក់ប្រហែលរបស់​ឧបករណ៍នេះ​ឬ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ជាក់លាក់"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ប្រហាក់ប្រហែល"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ប្រតិទិនរបស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ផ្ញើ និង​មើលសារ SMS ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​រូបថត មេឌៀ និងឯកសារនៅលើ​ឧបករណ៍របស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើប្រាស់&lt;b&gt;រូបថត វីដេអូ តន្ត្រី និងសំឡេង&lt;/b&gt;នៅលើឧបករណ៍នេះទេ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ &lt;b&gt;រូបថត វីដេអូ តន្ត្រី សំឡេង និងឯកសារផ្សេងទៀត&lt;/b&gt;នៅលើឧបករណ៍នេះទេ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើប្រាស់តន្ត្រី និងសំឡេងនៅលើឧបករណ៍នេះទេ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើប្រាស់រូបថត និងវីដេអូនៅលើឧបករណ៍នេះទេ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើប្រាស់រូបថត និងវីដេអូច្រើនទៀតនៅលើឧបករណ៍នេះឬ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតសំឡេង?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"កម្មវិធីនេះនឹងអាចថតសំឡេង នៅពេលអ្នកកំពុងប្រើប្រាស់កម្មវិធីតែប៉ុណ្ណោះ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតសំឡេងឬ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"កម្មវិធីនេះអាចចង់ថតសំឡេងគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើប្រាស់កម្មវិធីក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"ប្ដូរសិទ្ធិ​ចូលប្រើ​មីក្រូហ្វូន​សម្រាប់ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ឬ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"កម្មវិធីនេះចង់ថតសំឡេងគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើប្រាស់កម្មវិធីក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​សកម្មភាព​រាងកាយ​របស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតរូប និងថត​វីដេអូ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"កម្មវិធីនេះនឹងអាចថតរូប និងវីដេអូ នៅពេលអ្នកកំពុងប្រើប្រាស់កម្មវិធីតែប៉ុណ្ណោះ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតរូប និងថត​វីដេអូឬ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"កម្មវិធីនេះអាចចង់ថតរូប និងវីដេអូគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើប្រាស់កម្មវិធីក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"ប្ដូរសិទ្ធិ​ចូលប្រើ​កាមេរ៉ាសម្រាប់ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ឬ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"កម្មវិធីនេះចង់ថតរូប និងវីដេអូគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើប្រាស់កម្មវិធីក៏ដោយ។ "<annotation id="link">"អនុញ្ញាតនៅក្នុងការកំណត់។"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"អនុញ្ញាត​ឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូល​ប្រើ​កំណត់ហេតុ​ហៅទូរសព្ទ​របស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; គ្រប់គ្រង និង​ធ្វើការហៅទូរសព្ទ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ចូលប្រើ​ទិន្នន័យឧបករណ៍ចាប់សញ្ញាអំពីស្ថានភាពសុខភាពរបស់អ្នក?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ដើម្បីអនុញ្ញាតឱ្យកម្មវិធីនេះចូលប្រើទិន្នន័យឧបករណ៍ចាប់សញ្ញារាងកាយគ្រប់ពេល ទោះបីជានៅពេលអ្នកមិនកំពុងប្រើកម្មវិធីនេះក៏ដោយ "<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ផ្ញើ​ការជូនដំណឹង​ឱ្យអ្នកឬ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"ការអនុញ្ញាត​ដែលស្ថិតក្រោម​ការគ្រប់គ្រង"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> មានសិទ្ធិចូលប្រើទីតាំង"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ស្ថាប័នរបស់អ្នកអនុញ្ញាតឱ្យ <xliff:g id="APP_NAME">%1$s</xliff:g> ចូលប្រើទីតាំងរបស់អ្នក"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"កម្មវិធីនេះបានបញ្ជាក់ថា វាអាចចែករំលែកទិន្នន័យទីតាំងជាមួយភាគីទីបី"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ការចែករំលែកទិន្នន័យ និងទីតាំង"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"កន្លែងដែលព័ត៌មាន​អំពីការចែករំលែក​ទិន្នន័យបានមកពី"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"អ្នកអភិវឌ្ឍន៍បានផ្ដល់ព័ត៌មាន​ដល់ក្រុមហ៊ុនផលិតឧបករណ៍នេះ​អំពីរបៀបដែលកម្មវិធីនេះ​ចែករំលែកទិន្នន័យ។ អ្នក​អភិវឌ្ឍន៍អាចនឹងធ្វើបច្ចុប្បន្នភាព​ព័ត៌មាននេះ​ទៅតាមពេលវេលា។"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"អ្នកអភិវឌ្ឍន៍​បានផ្ដល់ព័ត៌មានដល់ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" អំពីរបៀបដែល​កម្មវិធីនេះ​ចែករំលែកទិន្នន័យ។ អ្នក​អភិវឌ្ឍន៍អាចនឹងធ្វើបច្ចុប្បន្នភាព​ព័ត៌មាននេះ​ទៅតាមពេលវេលា។"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"កម្មវិធីនេះ​អាចនឹងចែករំលែក​ទិន្នន័យទីតាំងសម្រាប់៖"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ភាពខុសគ្នានៃ​ការចែករំលែកទិន្នន័យ"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"សុវត្ថិភាព​ទិន្នន័យ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ទិន្នន័យទីតាំងអាចនឹង​ត្រូវបានចែករំលែក"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"កម្មវិធីនេះ​បានបញ្ជាក់ថា វាអាចចែករំលែក​ទិន្នន័យទីតាំងរបស់អ្នក​ជាមួយភាគីទីបី"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"មិនអាចបើកតំណនេះបានទេ"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"បច្ចុប្បន្នភាពការចែករំលែកទិន្នន័យសម្រាប់ទីតាំង"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ពិនិត្យមើលកម្មវិធីដែលបានផ្លាស់ប្ដូររបៀបដែលកម្មវិធីទាំងនោះអាចចែករំលែកទិន្នន័យទីតាំងរបស់អ្នក"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"កម្មវិធីទាំងនេះ​បានផ្លាស់ប្ដូររបៀបដែលវា​អាចចែករំលែកទិន្នន័យ​ទីតាំងរបស់អ្នក។ កម្មវិធីទាំងនេះ​ប្រហែលជាមិនបានចែករំលែកទិន្នន័យទីតាំងពីមុនទេ ឬឥឡូវនេះប្រហែលជា​ចែករំលែកទិន្នន័យទីតាំងនេះ​សម្រាប់គោលបំណង​ផ្សាយពាណិជ្ជកម្ម ឬធ្វើទីផ្សារ។"</string>
diff --git a/PermissionController/res/values-kn-v33/strings.xml b/PermissionController/res/values-kn-v33/strings.xml
index 8179b964a..f4d39d7ac 100644
--- a/PermissionController/res/values-kn-v33/strings.xml
+++ b/PermissionController/res/values-kn-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ಇನ್ನಷ್ಟು ಎಚ್ಚರಿಕೆಗಳು"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ವಜಾಗೊಳಿಸಿದ ಎಚ್ಚರಿಕೆಗಳು"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ವಿಸ್ತರಿಸಿ ಮತ್ತು ಇನ್ನೊಂದು ಎಚ್ಚರಿಕೆಯನ್ನು ನೋಡಿ}one{ವಿಸ್ತರಿಸಿ ಮತ್ತು # ಹೆಚ್ಚಿನ ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}other{ವಿಸ್ತರಿಸಿ ಮತ್ತು # ಹೆಚ್ಚಿನ ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ಅಲರ್ಟ್. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ಆ್ಯಕ್ಷನ್ ಪೂರ್ಣಗೊಂಡಿದೆ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ರಕ್ಷಣೆಯನ್ನು ಸೇರಿಸಬಹುದಾದ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"ಭದ್ರತೆ ಮತ್ತು ಗೌಪ್ಯತೆ ಕುರಿತ ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
diff --git a/PermissionController/res/values-kn/strings.xml b/PermissionController/res/values-kn/strings.xml
index 1698eea2c..8a74938ff 100644
--- a/PermissionController/res/values-kn/strings.xml
+++ b/PermissionController/res/values-kn/strings.xml
@@ -149,12 +149,12 @@
<string name="permission_usage_last_n_hours" msgid="8490466053680267858">"{count,plural, =1{# ಗಂಟೆಯ ಹಿಂದೆ}one{ಕೊನೆಯ # ಗಂಟೆಗಳು}other{ಕೊನೆಯ # ಗಂಟೆಗಳು}}"</string>
<string name="permission_usage_last_n_minutes" msgid="7817864229878281983">"{count,plural, =1{ಕಳೆದ # ನಿಮಿಷ}one{ಹಿಂದಿನ # ನಿಮಿಷಗಳು}other{ಹಿಂದಿನ # ನಿಮಿಷಗಳು}}"</string>
<string name="no_permission_usages" msgid="9119517454177289331">"ಅನುಮತಿಯ ಬಳಕೆಗಳು ಇಲ್ಲ"</string>
- <string name="permission_usage_list_title_any_time" msgid="8718257027381592407">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
- <string name="permission_usage_list_title_last_7_days" msgid="9048542342670890615">"ಕಳೆದ 7 ದಿನಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
- <string name="permission_usage_list_title_last_day" msgid="8730907824567238461">"ಕಳೆದ 24 ಗಂಟೆಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
- <string name="permission_usage_list_title_last_hour" msgid="6624161487623223716">"ಕಳೆದ 1 ಗಂಟೆಯಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
- <string name="permission_usage_list_title_last_15_minutes" msgid="8615062016024296833">"ಕಳೆದ 15 ನಿಮಿಷಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
- <string name="permission_usage_list_title_last_minute" msgid="3572792262919886849">"ಕಳೆದ 1 ನಿಮಿಷದಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಪ್ರವೇಶ"</string>
+ <string name="permission_usage_list_title_any_time" msgid="8718257027381592407">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="permission_usage_list_title_last_7_days" msgid="9048542342670890615">"ಕಳೆದ 7 ದಿನಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="permission_usage_list_title_last_day" msgid="8730907824567238461">"ಕಳೆದ 24 ಗಂಟೆಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="permission_usage_list_title_last_hour" msgid="6624161487623223716">"ಕಳೆದ 1 ಗಂಟೆಯಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="permission_usage_list_title_last_15_minutes" msgid="8615062016024296833">"ಕಳೆದ 15 ನಿಮಿಷಗಳಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="permission_usage_list_title_last_minute" msgid="3572792262919886849">"ಕಳೆದ 1 ನಿಮಿಷದಲ್ಲಿನ ತೀರಾ ಇತ್ತೀಚಿನ ಆ್ಯಕ್ಸೆಸ್"</string>
<string name="permission_usage_bar_chart_title_any_time" msgid="2845251288192246754">"ಯಾವುದೇ ಸಮಯದಲ್ಲಿನ ಅನುಮತಿಯ ಬಳಕೆ"</string>
<string name="permission_usage_bar_chart_title_last_7_days" msgid="5796577162176938349">"ಕಳೆದ 7 ದಿನಗಳಲ್ಲಿನ ಅನುಮತಿಯ ಬಳಕೆ"</string>
<string name="permission_usage_bar_chart_title_last_day" msgid="7950805735777472871">"ಕಳೆದ 24 ಗಂಟೆಗಳಲ್ಲಿನ ಅನುಮತಿಯ ಬಳಕೆ"</string>
@@ -181,8 +181,8 @@
<string name="permission_history_category_today" msgid="7496389369158806620">"ಇಂದು"</string>
<string name="permission_history_category_yesterday" msgid="7242517121222012521">"ನಿನ್ನೆ"</string>
<string name="app_permission_usage_title" msgid="6676802437831981822">"ಆ್ಯಪ್‌ ಅನುಮತಿಗಳ ಬಳಕೆ"</string>
- <string name="app_permission_usage_summary" msgid="390383661936709672">"ಪ್ರವೇಶ: <xliff:g id="NUM">%1$s</xliff:g> ಬಾರಿ. ಒಟ್ಟು ಅವಧಿ: <xliff:g id="DURATION">%2$s</xliff:g>. <xliff:g id="TIME">%3$s</xliff:g> ಸಮಯದ ಹಿಂದೆ ಕೊನೆಯದಾಗಿ ಬಳಸಲಾಗಿದೆ."</string>
- <string name="app_permission_usage_summary_no_duration" msgid="3698475875179457400">"ಪ್ರವೇಶ: <xliff:g id="NUM">%1$s</xliff:g> ಬಾರಿ. <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದ ಹಿಂದೆ ಕೊನೆಯದಾಗಿ ಬಳಸಲಾಗಿದೆ."</string>
+ <string name="app_permission_usage_summary" msgid="390383661936709672">"ಆ್ಯಕ್ಸೆಸ್: <xliff:g id="NUM">%1$s</xliff:g> ಬಾರಿ. ಒಟ್ಟು ಅವಧಿ: <xliff:g id="DURATION">%2$s</xliff:g>. <xliff:g id="TIME">%3$s</xliff:g> ಸಮಯದ ಹಿಂದೆ ಕೊನೆಯದಾಗಿ ಬಳಸಲಾಗಿದೆ."</string>
+ <string name="app_permission_usage_summary_no_duration" msgid="3698475875179457400">"ಆ್ಯಕ್ಸೆಸ್: <xliff:g id="NUM">%1$s</xliff:g> ಬಾರಿ. <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯದ ಹಿಂದೆ ಕೊನೆಯದಾಗಿ ಬಳಸಲಾಗಿದೆ."</string>
<string name="app_permission_button_allow" msgid="5808039516494774647">"ಅನುಮತಿಸಿ"</string>
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"ಎಲ್ಲಾ ಫೈಲ್‌ಗಳ ನಿರ್ವಹಣೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"ಮಾಧ್ಯಮಕ್ಕೆ ಮಾತ್ರ ಪ್ರವೇಶಿಸಲು ಅನುಮತಿಸಿ"</string>
@@ -241,7 +241,7 @@
<string name="permission_description_summary_storage" msgid="6575759089065303346">"ಈ ಅನುಮತಿಯ ಜೊತೆಗೆ ಆ್ಯಪ್‌ಗಳು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಮತ್ತು ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು"</string>
<string name="permission_description_summary_read_media_aural" msgid="3354728149930482199">"ಈ ಅನುಮತಿಯನ್ನು ಹೊಂದಿರುವ ಆ್ಯಪ್‌ಗಳು ಈ ಸಾಧನದಲ್ಲಿನ ಸಂಗೀತ ಮತ್ತು ಇತರ ಆಡಿಯೋ ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು"</string>
<string name="permission_description_summary_read_media_visual" msgid="4991801977881732641">"ಈ ಅನುಮತಿಯನ್ನು ಹೊಂದಿರುವ ಆ್ಯಪ್‌ಗಳು ಈ ಸಾಧನದಲ್ಲಿನ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಪ್ರವೇಶಿಸಬಹುದು"</string>
- <string name="app_permission_most_recent_summary" msgid="4292074449384040590">"ಕೊನೆಯ ಪ್ರವೇಶ:<xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
+ <string name="app_permission_most_recent_summary" msgid="4292074449384040590">"ಕೊನೆಯ ಆ್ಯಕ್ಸೆಸ್:<xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_most_recent_denied_summary" msgid="7659497197737708112">"ಪ್ರಸ್ತುತ ನಿರಾಕರಿಸಿರುವುದು / ಕೊನೆಯದಾಗಿ ಪ್ರವೇಶಿಸಿರುವುದು: <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
<string name="app_permission_never_accessed_summary" msgid="401346181461975090">"ಎಂದಿಗೂ ಪ್ರವೇಶಿಸಿಲ್ಲ"</string>
<string name="app_permission_never_accessed_denied_summary" msgid="6596000497490905146">"ನಿರಾಕರಿಸಲಾಗಿದೆ / ಎಂದಿಗೂ ಪ್ರವೇಶಿಸಲಾಗಿಲ್ಲ"</string>
@@ -282,13 +282,13 @@
<string name="auto_revoke_preference_summary" msgid="5517958331781391481">"ನಿಮ್ಮ ಗೌಪ್ಯತೆಯನ್ನು ರಕ್ಷಿಸಲು ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
<string name="background_location_access_reminder_notification_title" msgid="1140797924301941262">"<xliff:g id="APP_NAME">%s</xliff:g> ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಹಿನ್ನಲೆಯಲ್ಲಿ ಪಡೆದುಕೊಂಡಿದೆ"</string>
<string name="background_location_access_reminder_notification_content" msgid="7787084707336546245">"ಈ ಆ್ಯಪ್‌ ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು. ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
- <string name="notification_listener_reminder_notification_title" msgid="3747210460187479091">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳಿಗೆ ಪ್ರವೇಶ ಹೊಂದಿರುವ ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
+ <string name="notification_listener_reminder_notification_title" msgid="3747210460187479091">"ನಿಮ್ಮ ನೋಟಿಫಿಕೇಶನ್‌ಗಳಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುವ ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="notification_listener_reminder_notification_content" msgid="831476101108863427">"<xliff:g id="APP_NAME">%s</xliff:g> ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು, ಕ್ರಮ ಕೈಗೊಳ್ಳಬಹುದು ಹಾಗೂ ಅದರಲ್ಲಿರುವ ವಿಷಯವನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು"</string>
<string name="notification_listener_warning_card_content" msgid="7840973324284115893">"ಈ ಆ್ಯಪ್ ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಬಹುದು, ಕ್ರಮ ಕೈಗೊಳ್ಳಬಹುದು ಹಾಗೂ ಅದರಲ್ಲಿರುವ ವಿಷಯವನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಬಹುದು. ಕೆಲವು ಆ್ಯಪ್‌ಗಳು ಉದ್ದೇಶಿಸಿದಂತೆ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅವುಗಳಿಗೆ ಈ ಆ್ಯಕ್ಸೆಸ್‌ನ ಅಗತ್ಯವಿದೆ."</string>
<string name="notification_listener_remove_access_button_label" msgid="7101898782417817097">"ಪ್ರವೇಶವನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
<string name="notification_listener_review_app_button_label" msgid="3433073281029143924">"ಮತ್ತಷ್ಟು ಆಯ್ಕೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="notification_listener_remove_access_success_label" msgid="2477611529875633107">"ಪ್ರವೇಶವನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
- <string name="accessibility_access_reminder_notification_title" msgid="2971317234668807566">"ಪೂರ್ಣ ಸಾಧನ ಪ್ರವೇಶ ಹೊಂದಿರುವ ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
+ <string name="accessibility_access_reminder_notification_title" msgid="2971317234668807566">"ಪೂರ್ಣ ಸಾಧನ ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುವ ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="accessibility_access_reminder_notification_content" msgid="7389454158175306720">"<xliff:g id="APP_NAME">%s</xliff:g> ಆ್ಯಪ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಮತ್ತು ಸಾಧನದಲ್ಲಿ ಕ್ರಿಯೆಗಳನ್ನು ಮಾಡಬಹುದು. ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಆ್ಯಪ್‌ಗಳು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಈ ರೀತಿಯ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ."</string>
<string name="accessibility_access_warning_card_content" msgid="4370327190293217358">"ಈ ಆ್ಯಪ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದು ಮತ್ತು ಸಾಧನದಲ್ಲಿ ಕ್ರಿಯೆಗಳನ್ನು ಮಾಡಬಹುದು. ಆ್ಯಕ್ಸೆಸಿಬಿಲಿಟಿ ಆ್ಯಪ್‌ಗಳು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಈ ರೀತಿಯ ಪ್ರವೇಶದ ಅಗತ್ಯವಿದೆ, ಆದರೆ ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ ಮತ್ತು ನೀವು ಅದನ್ನು ನಂಬುತ್ತೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
<string name="accessibility_remove_access_button_label" msgid="44145801526711640">"ಪ್ರವೇಶವನ್ನು ತೆಗೆದುಹಾಕಿ"</string>
@@ -398,12 +398,12 @@
<string name="role_app_streaming_description" msgid="7341638576226183992">"ನಿಮ್ಮ ಅಧಿಸೂಚನೆಗಳೊಂದಿಗೆ ಸಂವಹನ ನಡೆಸಲು ಮತ್ತು ನಿಮ್ಮ ಆ್ಯಪ್‌ಗಳನ್ನು ಸಂಪರ್ಕಿತ ಸಾಧನಕ್ಕೆ ಸ್ಟ್ರೀಮ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸಲಾಗುತ್ತದೆ."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"ಈ ಸೇವೆಯು ನಿಮ್ಮ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ ಹಾಗೂ ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಮ್ಮ ಫೋನ್‌ನಿಂದ ಇತರ ಸಾಧನಗಳ ಜೊತೆ ಹಂಚಿಕೊಳ್ಳುತ್ತದೆ."</string>
<string name="role_notes_label" msgid="7451627001058089536">"ಡೀಫಾಲ್ಟ್ ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್"</string>
- <string name="role_notes_short_label" msgid="8796604147546125285">"ಟಿಪ್ಪಣಿಗಳ ಆ್ಯಪ್"</string>
+ <string name="role_notes_short_label" msgid="8796604147546125285">"ಟಿಪ್ಪಣಿಗಳು ಆ್ಯಪ್"</string>
<string name="role_notes_description" msgid="8496852798616883551">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಟಿಪ್ಪಣಿಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ನಿಮಗೆ ಅನುಮತಿಸುವ ಆ್ಯಪ್‌ಗಳು"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"ಟಿಪ್ಪಣಿಗಳು"</string>
<string name="request_role_current_default" msgid="738722892438247184">"ಪ್ರಸ್ತುತ ಡೀಫಾಲ್ಟ್"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"ಮತ್ತೆ ಕೇಳಬೇಡ"</string>
- <string name="request_role_set_as_default" msgid="4253949643984172880">"ಡೀಫಾಲ್ಟ್ ಆಗಿ ಹೊಂದಿಸಿ"</string>
+ <string name="request_role_set_as_default" msgid="4253949643984172880">"ಡೀಫಾಲ್ಟ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ"</string>
<string name="phone_call_uses_microphone" msgid="233569591461187177">"&lt;b&gt;ಫೋನ್ ಕರೆಯಲ್ಲಿ&lt;/b&gt; ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ"</string>
<string name="phone_call_uses_microphone_and_camera" msgid="6291898755681748189">"&lt;b&gt;ವೀಡಿಯೋ ಕರೆಯಲ್ಲಿ&lt;/b&gt; ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ"</string>
<string name="phone_call_uses_camera" msgid="2048417022147857418">"&lt;b&gt;ವೀಡಿಯೋ ಕರೆಯಲ್ಲಿ&lt;/b&gt; ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ"</string>
@@ -431,8 +431,8 @@
<string name="default_app_no_apps" msgid="115720991680586885">"ಯಾವುದೇ ಆ್ಯಪ್‌ಗಳು ಇಲ್ಲ"</string>
<string name="car_default_app_selected" msgid="5416420830430644174">"ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
<string name="car_default_app_selected_with_info" msgid="1932204186080593500">"<xliff:g id="ADDITIONAL_INFO">%1$s</xliff:g> - ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string>
- <string name="special_app_access_search_keyword" msgid="8032347212290774210">"ವಿಶೇಷ ಆ್ಯಪ್ ಪ್ರವೇಶ"</string>
- <string name="special_app_access" msgid="5019319067120213797">"ಆ್ಯಪ್‌ಗೆ ವಿಶೇಷ ಪ್ರವೇಶ"</string>
+ <string name="special_app_access_search_keyword" msgid="8032347212290774210">"ವಿಶೇಷ ಆ್ಯಪ್ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="special_app_access" msgid="5019319067120213797">"ಆ್ಯಪ್‌ಗೆ ವಿಶೇಷ ಆ್ಯಕ್ಸೆಸ್"</string>
<string name="no_special_app_access" msgid="6950277571805106247">"ಆ್ಯಪ್‌ಗೆ ವಿಶೇಷ ಪ್ರವೇಶವಿಲ್ಲ"</string>
<string name="special_app_access_no_apps" msgid="4102911722787886970">"ಯಾವುದೇ ಆ್ಯಪ್‌ಗಳು ಇಲ್ಲ"</string>
<string name="home_missing_work_profile_support" msgid="1756855847669387977">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"ಅಸಿಸ್ಟೆಂಟ್ ಮೈಕ್ರೋಫೋನ್ ಸಕ್ರಿಯವಾಗಿದೆ ಅಥವಾ ಇಲ್ಲವೇ ಎಂದು ತೋರಿಸಿ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ಧ್ವನಿ ಅಸಿಸ್ಟೆಂಟ್ ಸಕ್ರಿಯಗೊಳಿಸಲು ಮೈಕ್ರೊಫೋನ್ ಬಳಸಿದಾಗ ಸ್ಥಿತಿ ಬಾರ್‌ನಲ್ಲಿ ಐಕಾನ್ ಅನ್ನು ತೋರಿಸಿ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿರುವ ಫೋಟೋಗಳು ಮತ್ತು ಮೀಡಿಯಾ ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"ನಿಮ್ಮ ಸಂಪರ್ಕಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಬಳಸುವಾಗ, ಆ್ಯಪ್ ಮಾತ್ರ ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿರುತ್ತದೆ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ಈ ಸಾಧನದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಲು ಆ್ಯಪ್ ಬಯಸಬಹುದು. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗಾಗಿ ಸ್ಥಳ ಪ್ರವೇಶವನ್ನು ಬದಲಾಯಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಲು ಆ್ಯಪ್ ಬಯಸುತ್ತದೆ. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"ಸಮೀಪದ ಸಾಧನಗಳನ್ನು ಹುಡುಕಲು, ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ಮತ್ತು ಅವುಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"ಸಮೀಪದ ಸಾಧನಗಳನ್ನು ಹುಡುಕಲು, ಅವುಗಳಿಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ಮತ್ತು ಅವುಗಳ ಸಂಬಂಧಿತ ಸ್ಥಾನವನ್ನು ನಿರ್ಧರಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ? "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ನ ಸ್ಥಳ ಪ್ರವೇಶವನ್ನು ಅಂದಾಜಿನಿಂದ ನಿಖರತೆಗೆ ಬದಲಾಯಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ಈ ಸಾಧನದ ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ನಿಖರ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ಅಂದಾಜು"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"ನಿಮ್ಮ ಕ್ಯಾಲೆಂಡರ್ ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"ಎಸ್‌ಎಂಎಸ್‌ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಮತ್ತು ವೀಕ್ಷಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"ಸಾಧನದಲ್ಲಿ ಫೋಟೋಗಳು, ಮಾಧ್ಯಮ, ಫೈಲ್‌ಗಳನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ಈ ಸಾಧನದಲ್ಲಿರುವ &lt;b&gt;ಫೋಟೋಗಳು, ವೀಡಿಯೊಗಳು, ಸಂಗೀತ, ಆಡಿಯೊವನ್ನು&lt;/b&gt; ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ಈ ಸಾಧನದಲ್ಲಿರುವ &lt;b&gt;ಫೋಟೋಗಳು, ವೀಡಿಯೊಗಳು, ಸಂಗೀತ, ಆಡಿಯೋ, ಇತರ ಫೈಲ್‌ಗಳನ್ನು&lt;/b&gt; ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ಈ ಸಾಧನದಲ್ಲಿರುವ ಸಂಗೀತ ಮತ್ತು ಆಡಿಯೊವನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ಈ ಸಾಧನದಲ್ಲಿರುವ ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ಈ ಸಾಧನದಲ್ಲಿರುವ ಇನ್ನಷ್ಟು ಫೋಟೋಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ನೀವು ಆ್ಯಪ್ ಬಳಸುತ್ತಿರುವಾಗ ಮಾತ್ರ ಆ್ಯಪ್‌ಗೆ ಆಡಿಯೋ ರೆಕಾರ್ಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಈ ಆ್ಯಪ್ ಯಾವಾಗಲೂ ಆಡಿಯೊವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ಬಯಸಬಹುದು. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗಾಗಿ ಮೈಕ್ರೋಫೋನ್ ಪ್ರವೇಶವನ್ನು ಬದಲಾಯಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ನೀವು ಈ ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಈ ಆ್ಯಪ್ ಯಾವಾಗಲೂ ಆಡಿಯೊವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ಬಯಸುತ್ತದೆ. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"ನಿಮ್ಮ ದೈಹಿಕ ಚಟುವಟಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ಕ್ಕೆ ಅನುಮತಿಸುವುದೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"ಚಿತ್ರಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ವೀಡಿಯೊ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಬಳಸುತ್ತಿರುವಾಗ ಮಾತ್ರ ಆ್ಯಪ್‌ಗೆ ಚಿತ್ರಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಮತ್ತು ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗುತ್ತದೆ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"ಚಿತ್ರಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ವೀಡಿಯೊ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ನೀವು ಈ ಆ್ಯಪ್ ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಈ ಆ್ಯಪ್ ಎಲ್ಲಾ ಸಮಯದಲ್ಲೂ ಚಿತ್ರಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಮತ್ತು ವೀಡಿಯೊವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ಬಯಸಬಹುದು. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಆ್ಯಪ್‌ಗಾಗಿ ಕ್ಯಾಮರಾ ಪ್ರವೇಶವನ್ನು ಬದಲಾಯಿಸಬೇಕೆ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ನೀವು ಈ ಆ್ಯಪ್ ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಈ ಆ್ಯಪ್ ಎಲ್ಲಾ ಸಮಯದಲ್ಲೂ ಚಿತ್ರಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲು ಮತ್ತು ವೀಡಿಯೊವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ಬಯಸುತ್ತದೆ. "<annotation id="link">"ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಅನುಮತಿಸಿ."</annotation></string>
- <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_calllog" msgid="2065327180175371397">"ನಿಮ್ಮ ಫೋನ್‌ ಕರೆಯ ಲಾಗ್‌ಗಳಿಗೆ ಆ್ಯಕ್ಸೆಸ್ ಪಡೆಯಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ಬಳಸದಿರುವಾಗಲೂ ಸಹ, ಎಲ್ಲಾ ಸಮಯದಲ್ಲೂ ದೇಹದ ಸೆನ್ಸರ್‌ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಈ ಆ್ಯಪ್ ಅನ್ನು ಅನುಮತಿಸಲು, "<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="auto_granted_permissions" msgid="6009452264824455892">"ನಿಯಂತ್ರಿತ ಅನುಮತಿಗಳು"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"ನಿಮಗೆ ನೋಟಿಫಿಕೇಶನ್‌ಗಳನ್ನು ಕಳುಹಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"ನಿಯಂತ್ರಿತ ಅನುಮತಿಗಳು"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಸ್ಥಳ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ಹೊಂದಿದೆ"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="APP_NAME">%1$s</xliff:g> ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"ಇತರ ಅನುಮತಿಗಳು"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"ಸಿಸ್ಟಂನಿಂದ ಬಳಸಲ್ಪಡುವ ಅನುಮತಿಗಳು"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"ಸಿಸ್ಟಂ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಂದ ಮಾತ್ರ ಬಳಸಲ್ಪಡುವ ಅನುಮತಿಗಳು."</string>
@@ -514,8 +566,8 @@
<string name="privdash_label_none" msgid="5991866260360484858">"ಯಾವುದೂ ಅಲ್ಲ"</string>
<string name="privdash_label_24h" msgid="1512532123865375319">"ಕಳೆದ\n24 ಗಂಟೆಗಳು"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"ಕಳೆದ\n7 ದಿನಗಳಲ್ಲಿ"</string>
- <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅನ್ನು Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+ <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g>, Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಸ್ಥಿತಿ ಪಟ್ಟಿಯಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g>, Android ನಿಂದ ರಕ್ಷಣೆ ಪಡೆದಿದೆ. ಈ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗಿರುವುದರಿಂದ, ಈ ಆ್ಯಪ್‌ನ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ನಿಮ್ಮ ಗೌಪ್ಯತಾ ಡ್ಯಾಶ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ತೋರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"ಸಾಧನದ ಕ್ಯಾಮರಾವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"ಸಾಧನದ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"ಸಾಧನದ ಸ್ಥಳವು ಆಫ್ ಆಗಿದೆ"</string>
@@ -579,18 +631,19 @@
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"ಆ್ಯಕ್ಸೆಸ್ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"ಇತ್ತೀಚಿನ ಸ್ಥಳದ ಬಳಕೆಯನ್ನು ನೋಡಿ"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"ಗೌಪ್ಯತೆ ನಿಯಂತ್ರಣಗಳು"</string>
- <string name="camera_toggle_title" msgid="1251201397431837666">"ಕ್ಯಾಮರಾ ಪ್ರವೇಶ"</string>
- <string name="mic_toggle_title" msgid="2649991093496110162">"ಮೈಕ್ರೊಫೋನ್ ಪ್ರವೇಶ"</string>
+ <string name="camera_toggle_title" msgid="1251201397431837666">"ಕ್ಯಾಮರಾ ಆ್ಯಕ್ಸೆಸ್"</string>
+ <string name="mic_toggle_title" msgid="2649991093496110162">"ಮೈಕ್ರೊಫೋನ್ ಆ್ಯಕ್ಸೆಸ್"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸೇವೆಗಳಿಗಾಗಿ"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸೇವೆಗಳಿಗಾಗಿ. ಈ ಸೆಟ್ಟಿಂಗ್ ಆಫ್ ಆಗಿದ್ದರೆ, ನೀವು ತುರ್ತು ಸಂಖ್ಯೆಗೆ ಕರೆ ಮಾಡಿದಾಗ ಮೈಕ್ರೊಫೋನ್ ಡೇಟಾವನ್ನು ಆಗಲೂ ಹಂಚಿಕೊಳ್ಳಬಹುದು."</string>
- <string name="location_settings_subtitle" msgid="2328360561197430695">"ಸ್ಥಳಕ್ಕೆ ಪ್ರವೇಶ ಹೊಂದಿರುವ ಆ್ಯಪ್‌ಗಳು ಹಾಗೂ ಸೇವೆಗಳನ್ನು ನೋಡಿ"</string>
- <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಪ್ರವೇಶವನ್ನು ತೋರಿಸಿ"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"ನೀವು ನಕಲಿಸಿರುವ ಪಠ್ಯ, ಚಿತ್ರಗಳು ಅಥವಾ ಇತರ ವಿಷಯವನ್ನು ಆ್ಯಪ್‌ಗಳು ಪ್ರವೇಶಿಸಿದಾಗ ಸಂದೇಶವೊಂದನ್ನು ತೋರಿಸಿ"</string>
+ <string name="location_settings_subtitle" msgid="2328360561197430695">"ಸ್ಥಳಕ್ಕೆ ಆ್ಯಕ್ಸೆಸ್ ಹೊಂದಿರುವ ಆ್ಯಪ್‌ಗಳು ಹಾಗೂ ಸೇವೆಗಳನ್ನು ನೋಡಿ"</string>
+ <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ಆ್ಯಕ್ಸೆಸ್ ಅನ್ನು ತೋರಿಸಿ"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"ನೀವು ನಕಲಿಸಿರುವ ಪಠ್ಯ, ಚಿತ್ರಗಳು ಅಥವಾ ಇತರ ವಿಷಯವನ್ನು ಆ್ಯಪ್‌ಗಳು ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಿದಾಗ ಸಂದೇಶವೊಂದನ್ನು ತೋರಿಸಿ"</string>
<string name="show_password_title" msgid="2877269286984684659">"ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
<string name="show_password_summary" msgid="1110166488865981610">"ನೀವು ಟೈಪ್ ಮಾಡಿದಂತೆ ಅಕ್ಷರಗಳನ್ನು ಸಂಕ್ಷಿಪ್ತವಾಗಿ ಪ್ರದರ್ಶಿಸಿ"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ಈ ಆ್ಯಪ್ ಥರ್ಡ್ ಪಾರ್ಟಿಗಳೊಂದಿಗೆ ಸ್ಥಳ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು ಎಂದು ಉಲ್ಲೇಖಿಸಿದೆ"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ಡೇಟಾ ಹಂಚಿಕೆ ಮತ್ತು ಸ್ಥಳ"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ಡೇಟಾ ಹಂಚಿಕೆಯ ಮಾಹಿತಿಯು ಎಲ್ಲಿಂದ ಬರುತ್ತದೆ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ಈ ಆ್ಯಪ್ ಡೇಟಾವನ್ನು ಹೇಗೆ ಹಂಚಿಕೊಳ್ಳುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ಡೆವಲಪರ್ ಈ ಸಾಧನದ ತಯಾರಕರಿಗೆ ಮಾಹಿತಿಯನ್ನು ಒದಗಿಸಿದ್ದಾರೆ. ಡೆವಲಪರ್ ಕಾಲಕ್ರಮೇಣ ಈ ಮಾಹಿತಿಯನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ಈ ಆ್ಯಪ್, ಡೇಟಾವನ್ನು ಹೇಗೆ ಹಂಚಿಕೊಳ್ಳುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ಡೆವಲಪರ್ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" ಗೆ ಮಾಹಿತಿ ಒದಗಿಸಿದ್ದಾರೆ. ಡೆವಲಪರ್ ಕಾಲಕ್ರಮೇಣ ಈ ಮಾಹಿತಿಯನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಬಹುದು."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ಈ ಆ್ಯಪ್ ಇವುಗಳಿಗಾಗಿ ಸ್ಥಳ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ಡೇಟಾ ಹಂಚಿಕೆ ಬದಲಾಗುತ್ತದೆ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ಡೇಟಾ ಸುರಕ್ಷತೆ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ಸ್ಥಳ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ಈ ಆ್ಯಪ್, ಥರ್ಡ್-ಪಾರ್ಟಿಗಳೊಂದಿಗೆ ನಿಮ್ಮ ಸ್ಥಳ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು ಎಂದು ತಿಳಿಸಿದೆ"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ಈ ಲಿಂಕ್ ತೆರೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ಸ್ಥಳಕ್ಕಾಗಿ ಡೇಟಾ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ ಕುರಿತ ಅಪ್‌ಡೇಟ್‌ಗಳು"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ನಿಮ್ಮ ಸ್ಥಳ ಡೇಟಾವನ್ನು ತಾವು ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ವಿಧಾನವನ್ನು ಬದಲಾಯಿಸಿದ ಆ್ಯಪ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ನಿಮ್ಮ ಸ್ಥಳ ಡೇಟಾವನ್ನು ಈ ಆ್ಯಪ್‌ಗಳು ಹಂಚಿಕೊಳ್ಳಬಹುದಾದ ವಿಧಾನವನ್ನು ಅವು ಬದಲಾಯಿಸಿವೆ. ಇವು ಇದನ್ನು ಈ ಮೊದಲು ಹಂಚಿಕೊಂಡಿಲ್ಲದಿರಬಹುದು ಅಥವಾ ಈಗ ಅದನ್ನು ಜಾಹೀರಾತು ಅಥವಾ ಮಾರ್ಕೆಟಿಂಗ್ ಉದ್ದೇಶಗಳಿಗಾಗಿ ಹಂಚಿಕೊಳ್ಳುತ್ತಿರಬಹುದು."</string>
diff --git a/PermissionController/res/values-ko-v33/strings.xml b/PermissionController/res/values-ko-v33/strings.xml
index 5e7203b67..87bd343e9 100644
--- a/PermissionController/res/values-ko-v33/strings.xml
+++ b/PermissionController/res/values-ko-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"알림 더보기"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"닫은 알림"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{펼쳐서 알림 1개 더보기}other{펼쳐서 알림 #개 더보기}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"주의. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"작업 완료"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"기기 보안을 강화할 수 있는 설정 확인"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"보안 및 개인 정보 보호 빠른 설정"</string>
diff --git a/PermissionController/res/values-ko-v34/strings.xml b/PermissionController/res/values-ko-v34/strings.xml
index 93addd649..7b3091170 100644
--- a/PermissionController/res/values-ko-v34/strings.xml
+++ b/PermissionController/res/values-ko-v34/strings.xml
@@ -23,5 +23,5 @@
<string name="health_connect_summary" msgid="815473513776882296">"건강 데이터에 대한 앱 액세스 제어"</string>
<string name="location_settings" msgid="8863940440881290182">"위치 정보 액세스"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"앱 및 서비스에 적용됩니다. 설정이 꺼져 있어도 긴급 전화번호로 전화를 걸 때 마이크 데이터가 계속 공유될 수 있습니다."</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"앱 및 서비스에 적용됩니다."</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"앱 및 서비스에 적용"</string>
</resources>
diff --git a/PermissionController/res/values-ko/strings.xml b/PermissionController/res/values-ko/strings.xml
index 1e3e0db0c..8fbab3155 100644
--- a/PermissionController/res/values-ko/strings.xml
+++ b/PermissionController/res/values-ko/strings.xml
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"마지막 실행 날짜: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"모든 파일 관리를 허용하면 앱이 이 기기의 공통 저장용량 또는 연결된 저장장치에 있는 모든 파일에 액세스하거나 이러한 파일을 수정, 삭제할 수 있습니다. 앱이 사용자에게 요청하지 않고도 파일에 액세스할 수 있습니다."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"앱이 이 기기 또는 연결된 저장장치에 있는 파일에 액세스하거나 이러한 파일을 수정, 삭제하도록 허용하시겠습니까? 앱이 사용자에게 요청하지 않고도 파일에 액세스할 수 있습니다."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"이 권한이 있는 앱은 <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"이 권한이 있는 앱은 다음 작업을 할 수 있습니다: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"이 권한이 있는 앱은 걷기, 자전거 타기, 운전, 걸음 수 등 내 신체 활동 정보에 액세스할 수 있습니다."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"이 권한이 있는 앱은 내 캘린더에 액세스할 수 있습니다."</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"이 권한이 있는 앱은 전화 통화 기록을 읽고 쓸 수 있습니다."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"지원 앱 트리거 감지 표시"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"음성 어시스턴트 활성화를 위해 마이크가 사용되면 상태 표시줄에 아이콘 표시"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 사진 및 미디어에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 연락처에 액세스하도록 허용하시겠습니까?"</string>
- <string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 기기의 위치 정보에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
+ <string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 이 기기의 위치 정보에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"앱을 사용할 때만 앱에서 위치에 액세스합니다."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 기기의 위치 정보에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"앱을 사용하고 있지 않을 때도 앱에서 내 위치에 항상 액세스하려고 할 수 있습니다. "<annotation id="link">"설정에서 액세스를 허용"</annotation>"하세요."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;의 위치 액세스 권한을 변경하시겠습니까?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"앱을 사용하고 있지 않을 때도 앱에서 내 위치에 항상 액세스하려고 합니다. "<annotation id="link">"설정에서 액세스를 허용"</annotation>"하세요."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 근처에 있는 기기를 찾아 연결하고 기기 간 상대적 위치를 파악하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 근처 기기를 찾아 연결하고 기기 간 상대적 위치를 파악하도록 허용하시겠습니까? "<annotation id="link">"설정에서 허용하세요."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>의 위치 정보 액세스 권한을 대략적인 위치에서 정확한 위치로 변경하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 대략적인 위치에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"정확한 위치"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"대략적인 위치"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 캘린더에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 SMS 메시지를 전송하고 보도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 사진, 미디어, 파일에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 &lt;b&gt;사진, 동영상, 음악, 오디오&lt;/b&gt;에 액세스하도록 허용하시겠습니까?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 &lt;b&gt;사진, 동영상, 음악, 오디오, 기타 파일&lt;/b&gt;에 액세스하도록 허용하시겠습니까?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 음악과 오디오에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기의 사진과 동영상에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 기기에 있는 더 많은 사진과 동영상에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 오디오를 녹음하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"앱을 사용하고 있는 동안에만 앱에서 오디오를 녹음할 수 있습니다."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 오디오를 녹음하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"앱을 사용하고 있지 않을 때도 앱에서 항상 오디오를 녹음하고자 할 수 있습니다. "<annotation id="link">"설정에서 액세스를 허용하세요"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;의 마이크 액세스 권한을 변경하시겠습니까?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"앱을 사용하고 있지 않을 때도 앱에서 항상 오디오를 녹음하려고 합니다. "<annotation id="link">"설정에서 액세스를 허용하세요"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 신체 활동 정보에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 사진을 촬영하고 동영상을 녹화하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"앱을 사용하고 있는 동안에만 앱에서 사진을 촬영하고 동영상을 녹화할 수 있습니다."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 사진을 촬영하고 동영상을 녹화하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"앱을 사용하고 있지 않을 때도 앱에서 항상 사진을 촬영하고 동영상을 녹화하고자 할 수 있습니다. "<annotation id="link">"설정에서 액세스를 허용하세요"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;의 카메라 액세스 권한을 변경하시겠습니까?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"앱을 사용하고 있지 않을 때도 앱에서 항상 사진을 촬영하고 동영상을 녹화하려고 합니다. "<annotation id="link">"설정에서 액세스를 허용하세요"</annotation>"."</string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 통화 기록에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 전화를 걸고 관리하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 생체 신호에 관한 센서 데이터에 액세스하도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"앱을 사용하지 않을 때도 앱이 항상 생체 신호 센서 데이터에 액세스하도록 허용하려면 "<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="auto_granted_permissions" msgid="6009452264824455892">"관리 대상 권한"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 알림을 보내도록 허용하시겠습니까?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"관리 대상 권한"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱이 위치 액세스 권한을 보유함"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"조직에서 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱이 내 위치에 액세스하도록 허용했습니다."</string>
<string name="other_permissions_label" msgid="8986184335503271992">"기타 권한"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"시스템에서 사용하는 권한"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"시스템 애플리케이션에서만 사용하는 권한입니다."</string>
@@ -572,10 +624,10 @@
<string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"앱이 최신 버전의 Android를 지원하지 않습니다. 앱이 음악 및 오디오 파일에 액세스할 수 없는 경우 사진 및 동영상에 대한 액세스도 허용되지 않습니다."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"앱이 최신 버전의 Android를 지원하지 않습니다. 앱이 사진 및 동영상에 액세스할 수 있는 경우 음악 및 오디오 파일에 대한 액세스도 허용됩니다."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"앱이 최신 버전의 Android를 지원하지 않습니다. 앱이 음악 및 오디오 파일에 액세스할 수 없는 경우 사진 및 동영상에 대한 액세스도 허용되지 않습니다."</string>
- <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"백그라운드 위치 액세스 권한이 있는 앱 검토하기"</string>
+ <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"백그라운드 위치 정보 액세스 권한이 있는 앱 검토하기"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> 앱은 닫혀 있는 동안에도 내 위치 정보에 항상 액세스할 수 있습니다."</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"백그라운드 위치 액세스 권한이 있는 앱 검토하기"</string>
- <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"이 앱은 앱이 닫혀 있는 동안에도 내 위치 정보에 항상 액세스할 수 있습니다.\n\n일부 안전 및 긴급 대응 앱은 의도한 대로 작동하기 위해 백그라운드에서 내 위치 정보에 액세스하는 권한이 필요합니다."</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"백그라운드 위치 정보 액세스 권한이 있는 앱 검토하기"</string>
+ <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"이 앱은 닫혀 있는 동안에도 내 위치 정보에 항상 액세스할 수 있습니다.\n\n일부 안전 및 긴급 대응 앱은 의도한 대로 작동하기 위해 백그라운드에서 내 위치 정보에 액세스할 수 있는 권한이 필요합니다."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"액세스 권한이 변경되었습니다."</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"최근 위치 정보 사용 내역 보기"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"개인 정보 보호 설정"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"앱에서 위치 데이터를 서드 파티와 공유할 수 있다고 명시했습니다."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"데이터 공유 및 위치"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"데이터 공유 정보 출처"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"개발자가 이 기기의 제조업체에 이 앱의 데이터 공유 방법에 관한 정보를 제공했습니다. 시간이 지난 후 개발자가 이 정보를 업데이트할 수도 있습니다."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"개발자가 "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"에게 이 앱의 데이터 공유 방법에 관한 정보를 제공했습니다. 시간이 지난 후 개발자가 이 정보를 업데이트할 수도 있습니다."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"이 앱은 다음 목적으로 위치 데이터를 공유할 수 있습니다."</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"다양한 데이터 공유 방식"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"데이터 보안"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"위치 데이터가 공유될 수 있습니다."</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"앱에서 위치 데이터를 서드 파티와 공유할 수 있다고 명시했습니다."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"링크를 열 수 없음"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"위치 데이터 공유 방법 업데이트"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"위치 데이터 공유 방법을 변경한 앱 검토"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"다음 앱에서 위치 데이터 공유 방법을 변경했습니다. 이전에 위치 데이터를 공유하지 않았던 앱이거나, 이제 광고 또는 마케팅 목적으로 데이터를 공유하는 앱일 수 있습니다."</string>
diff --git a/PermissionController/res/values-ky-television/strings.xml b/PermissionController/res/values-ky-television/strings.xml
index 138b37a9c..2e98e1503 100644
--- a/PermissionController/res/values-ky-television/strings.xml
+++ b/PermissionController/res/values-ky-television/strings.xml
@@ -19,7 +19,7 @@
<string name="grant_dialog_button_deny_dont_ask_again" msgid="747769682501286250">"Баш тартам жана экинчи суралбасын"</string>
<string name="grant_dialog_how_to_change" msgid="997462845048160559">"Муну кийин Параметрлер &gt; Колдонмолордон өзгөртө аласыз"</string>
<string name="current_permission_template" msgid="6240787325714651204">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="preference_show_system_apps" msgid="4262140518693221093">"Тутум колдонмолорун көрсөтүү"</string>
+ <string name="preference_show_system_apps" msgid="4262140518693221093">"Система колдонмолорун көрсөтүү"</string>
<string name="app_permissions_decor_title" msgid="7438716722786036814">"Колдонмонун уруксаттары"</string>
<string name="manage_permissions_decor_title" msgid="4138423885439613577">"Колдонмонун уруксаттары"</string>
<string name="permission_apps_decor_title" msgid="2811550489429789828">"<xliff:g id="PERMISSION">%1$s</xliff:g> уруксаттары"</string>
diff --git a/PermissionController/res/values-ky-v33/strings.xml b/PermissionController/res/values-ky-v33/strings.xml
index 8f88e1c93..3f2e12a3d 100644
--- a/PermissionController/res/values-ky-v33/strings.xml
+++ b/PermissionController/res/values-ky-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Дагы эскертүүлөр"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Жабылган эскертүүлөр"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Дагы бир эскертүүнү көрүү үчүн жайып көрсөтүү}other{Дагы # эскертүүнү көрүү үчүн жайып көрсөтүү}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Эскертүү. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Аракет аткарылды"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Түзмөгүңүздүн коопсуздугун бекемдей турган параметрлерди текшериңиз"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Коопсуздук жана купуялык ыкчам параметрлери"</string>
diff --git a/PermissionController/res/values-ky-v34/strings.xml b/PermissionController/res/values-ky-v34/strings.xml
index c21edf61f..15fc8424e 100644
--- a/PermissionController/res/values-ky-v34/strings.xml
+++ b/PermissionController/res/values-ky-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Коопсуздук жана купуялык"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Башкаруу элементтери"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Колдонмонун ден соолук тууралуу маалыматка кирүү мүмкүнчүлүгүн тескөө"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Колдонмо үчүн ден соолукка байланыштуу нерселердин жеткиликтүүлүгүн тескейсиз"</string>
<string name="location_settings" msgid="8863940440881290182">"Жайгашкан жерди көрсөтүү"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Колдонмолор жана кызматтар үчүн. Эгер бул жөндөө өчүрүлсө, кырсыктаганда жардамга келчү кызматтын номерине чалганыңызда микрофондогу нерселер өткөрүлүшү мүмкүн"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Колдонмолор жана кызматтар үчүн. Бул параметр өчүп турса да, кырсыктаганда жардамга келчү кызматтын номерине чалганыңызда микрофондогу нерселер өткөрүлүшү мүмкүн."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Колдонмолор жана кызматтар үчүн"</string>
</resources>
diff --git a/PermissionController/res/values-ky-watch/strings.xml b/PermissionController/res/values-ky-watch/strings.xml
index a40c90370..d6ca47fc1 100644
--- a/PermissionController/res/values-ky-watch/strings.xml
+++ b/PermissionController/res/values-ky-watch/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="grant_dialog_button_deny_dont_ask_again" msgid="5709879604352260492">"Баш тарам, экинчи суралбасын"</string>
<string name="current_permission_template" msgid="6634462553790549887">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="preference_show_system_apps" msgid="1055740303992024300">"Тутум колдонмолорун көрсөтүү"</string>
+ <string name="preference_show_system_apps" msgid="1055740303992024300">"Система колдонмолорун көрсөтүү"</string>
<string name="permission_summary_enforced_by_policy" msgid="2352478756952948019">"Өзгөртүүгө болбойт"</string>
<string name="generic_yes" msgid="2489207724988649846">"Ооба"</string>
<string name="generic_cancel" msgid="2631708607129269698">"Жок"</string>
diff --git a/PermissionController/res/values-ky/strings.xml b/PermissionController/res/values-ky/strings.xml
index 9372921a1..73ec0f075 100644
--- a/PermissionController/res/values-ky/strings.xml
+++ b/PermissionController/res/values-ky/strings.xml
@@ -60,7 +60,7 @@
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"Колдонмолор"</string>
<string name="app_permissions" msgid="3369917736607944781">"Колдонмонун уруксаттары"</string>
<string name="unused_apps" msgid="2058057455175955094">"Колдонулбаган колдонмолор"</string>
- <string name="no_unused_apps" msgid="12809387670415295">"Бардык колдонмолор иштетилүүдө"</string>
+ <string name="no_unused_apps" msgid="12809387670415295">"Бардык колдонмолор колдонулууда"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"Колдонулбаган колдонмолор: 0"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"Уруксаттарга байланыштуу аракеттер"</string>
<string name="review_permission_decisions_view_all" msgid="90391040431566130">"Уруксаттар боюнча көрүлгөн соңку аракеттер"</string>
@@ -273,7 +273,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>
- <string name="go_to_settings" msgid="1053735612211228335">"Жөндөөлөргө өтүү"</string>
+ <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>
@@ -351,9 +351,9 @@
<string name="role_assistant_short_label" msgid="3369003713187703399">"Санариптик жардамчы колдонмосу"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"Көмөкчү колдонмолор экранда көргөн маалыматыңыздын негизинде сизге жардам бере алат. Айрым колдонмолор жүргүзгүчтү жана айтып киргизүү функциясын да колдоого алат."</string>
<string name="role_browser_label" msgid="2877796144554070207">"Демейки серепчи"</string>
- <string name="role_browser_short_label" msgid="6745009127123292296">"\"Серепчи\" колдонмосу"</string>
+ <string name="role_browser_short_label" msgid="6745009127123292296">"Серепчи колдонмосу"</string>
<string name="role_browser_description" msgid="3465253637499842671">"Сайттарга кирип, шилтемелер боюнча өткөнгө мүмкүнчүлүк берген колдонмолор."</string>
- <string name="role_browser_request_title" msgid="2895200507835937192">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун демейки \"серепчи\" колдонмосу катары коёсузбу?"</string>
+ <string name="role_browser_request_title" msgid="2895200507835937192">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосун демейки серепчи колдонмосу катары коёсузбу?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"Уруксаттардын кереги жок"</string>
<string name="role_dialer_label" msgid="1100224146343237968">"Демейки телефон колдонмосу"</string>
<string name="role_dialer_short_label" msgid="7186888549465352489">"\"Телефон\" колдонмосу"</string>
@@ -442,68 +442,120 @@
<string name="incident_report_notification_title" msgid="4635984625656519773">"Мүчүлүштүктөрдү аныктоо дайындары бөлүшүлсүнбү?"</string>
<string name="incident_report_notification_text" msgid="3376480583513587923">"<xliff:g id="APP_NAME">%1$s</xliff:g> мүчүлүштүктөрдү оңдоо маалыматын жүктөп бергиси келет."</string>
<string name="incident_report_dialog_title" msgid="669104389325204095">"Мүчүлүштүктөр тууралуу кабарлансынбы?"</string>
- <string name="incident_report_dialog_intro" msgid="5897733669850951832">"Тутум бир мүчүлүштүктү аныктады."</string>
+ <string name="incident_report_dialog_intro" msgid="5897733669850951832">"Система бир мүчүлүштүктү аныктады."</string>
<string name="incident_report_dialog_text" msgid="5675553296891757523">"\"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" колдонмосу ушул түзмөктөн <xliff:g id="DATE">%2$s</xliff:g>, саат <xliff:g id="TIME">%3$s</xliff:g> түзүлгөн мүчүлүштүктөр тууралуу отчетту жүктөп берүүнү сурап жатат. Отчетто колдонуучулардын аттары, жүргөн жерлери, түзмөктүн идентификаторлору жана тармактын дайын-даректери сыяктуу түзмөгүңүздөгү же колдонмолоруңуздагы жеке маалымат камтылышы мүмкүн. Андыктан мүчүлүштүктөр тууралуу отчетту ишенимдүү адамдар жана колдонмолор менен гана бөлүшүңүз. \"<xliff:g id="APP_NAME_1">%4$s</xliff:g>\" колдонмосуна мүчүлүштүк тууралуу отчетту жүктөөгө уруксат бересизби?"</string>
<string name="incident_report_error_dialog_text" msgid="4189647113387092272">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы мүчүлүштүк тууралуу кабарды иштетүүдө ката кетти. Мүчүлүштүктөрдү аныктоо тууралуу кеңири маалыматтарды бөлүшүү сурамы четке кагылды. Ыңгайсыздык үчүн кечирим сурайбыз."</string>
<string name="incident_report_dialog_allow_label" msgid="2970242967721155239">"Уруксат берүү"</string>
<string name="incident_report_dialog_deny_label" msgid="3535314290677579383">"Тыюу салынат"</string>
<string name="adjust_user_sensitive_title" msgid="4196724451314280527">"Өркүндөтүлгөн жөндөөлөр"</string>
<string name="menu_adjust_user_sensitive" msgid="6497923610654425780">"Өркүндөтүлгөн жөндөөлөр"</string>
- <string name="adjust_user_sensitive_globally_title" msgid="8649190949066029174">"Тутум колдонмолорунун колдонгондугун көрсөтүү"</string>
+ <string name="adjust_user_sensitive_globally_title" msgid="8649190949066029174">"Система колдонмолорунун колдонгондугун көрсөтүү"</string>
<string name="adjust_user_sensitive_globally_summary" msgid="129467818433773912">"Системанын уруксаттарды колдонгондугу абал тилкесинде, куралдар тактасында жана башка жерде көрүнөт"</string>
<string name="adjust_user_sensitive_per_app_header" msgid="4543506440989005648">"Тандалган колдонмолорду көрсөтүү"</string>
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Үн жардамчысынын иштегенин чагылдырган сүрөтчөнү көрсөтүү"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Үн жардамчысын иштетүү үчүн микрофон колдонулганда, абал тилкесинде сүрөтчө көрүнөт"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу үчүн түзмөгүңүздөгү сүрөттөр менен мультимедиа файлдарын иштетесизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна байланыштарыңызды жеткиликтүү кыласызбы?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна бул түзмөктүн жайгашкан жерин көрүүгө уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Колдонмону колдонуп жаткан маалда гана, ал сиздин кайда жүргөнүңүздү билип турат."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна бул түзмөктүн жайгашкан жерин көрүүгө уруксат бересизби?"</string>
- <string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Бул колдонмо кайда жүргөнүңүздү ар дайым, колдонмону пайдаланбай турганда да, көрүүгө уруксат сурашы мүмкүн. "<annotation id="link">"Жөндөөлөрдөн уруксат бериңиз."</annotation></string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Бул колдонмо кайда жүргөнүңүздү ар дайым, колдонмону пайдаланбай турганда да, көрүүгө уруксат сурашы мүмкүн. "<annotation id="link">"Параметрлерден уруксат бериңиз."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу үчүн түзмөктүн жайгашкан жерин пайдалануу мүмкүнчүлүгү өзгөртүлсүнбү?"</string>
- <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Бул колдонмо кайда жүргөнүңүздү ар дайым, колдонмону пайдаланбай турганда да, көрүүгө уруксат сурап жатат. "<annotation id="link">"Жөндөөлөрдөн уруксат бериңиз."</annotation></string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Бул колдонмо кайда жүргөнүңүздү ар дайым, колдонмону пайдаланбай турганда да, көрүүгө уруксат сурап жатат. "<annotation id="link">"Параметрлерден уруксат бериңиз."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жакын жердеги түзмөктөрдү таап, аларга туташып жана абалын аныктай берсинби?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жакын жердеги түзмөктөрдү таап, аларга туташып жана абалын аныктай алсынбы? "<annotation id="link">"Жөндөөлөрдөн уруксат берүү."</annotation></string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; жакын жердеги түзмөктөрдү таап, аларга туташып жана абалын аныктай алсынбы? "<annotation id="link">"Параметрлерден уруксат берүү."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> колдонмосунда жайгашкан жер болжолдуу эмес, так аныкталсынбы?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна бул түзмөктүн болжолдуу жайгашкан жерин пайдаланууга уруксат берилсинби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Так"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Болжолдуу"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна жылнаамаңызды пайдаланууга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна SMS билдирүүлөрдү жөнөтүүгө жана окууга уруксат берилсинби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна түзмөгүңүздөгү сүрөттөрдү жана башка мультимедиа файлдарын пайдаланууга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна ушул түзмөктөгү &lt;b&gt;сүрөттөрдү, видеолорду, ырларды жана аудио файлдарды&lt;/b&gt; жеткиликтүү кыласызбы?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна ушул түзмөктөгү &lt;b&gt;сүрөттөрдү, видеолорду, ырларды, аудио файлдарды жана башка нерселерди&lt;/b&gt; жеткиликтүү кыласызбы?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна ушул түзмөктөгү ырлар менен аудио файлдарды жеткиликтүү кыласызбы?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна ушул түзмөктөгү сүрөттөр менен видеолорду жеткиликтүү кыласызбы?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна ушул түзмөктөгү дагы башка сүрөттөр менен видеолорду жеткиликтүү кыласызбы?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна аудио файлдарды жаздырганга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Колдонмону колдонуп жатканда гана, ал аудио жаздыра алат"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна аудио файлдарды жаздырууга уруксат бересизби?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Бул колдонмону колдонбой турсаңыз деле, ал такай аудио жаздыра берет. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу үчүн микрофонду пайдалануу мүмкүнчүлүгүн өзгөртөсүзбү?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Бул колдонмону колдонбой турсаңыз деле, ал такай аудио жаздыра берет. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна кыймыл-аракеттериңизге көз салып турганга мүмкүнчүлүк бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сүрөттөр менен видеолорду тартканга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Колдонмону колдонуп жатканда гана, ал сүрөт жана видео тарта алат"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сүрөт менен видео тартууга уруксат бересизби?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Бул колдонмону колдонбой турсаңыз деле, ал такай сүрөт жана видео тарта берет. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосу үчүн камераны пайдалануу мүмкүнчүлүгүн өзгөртөсүзбү?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Бул колдонмону колдонбой турсаңыз деле, ал такай сүрөт жана видео тарта берет. "<annotation id="link">"Ага жөндөөлөрдөн уруксат бериңиз."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна телефондогу чалуулар тизмесин пайдаланууга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна телефон чалууга жана чалууларды башкарууга уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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="6651914048792092835">"Бул колдонмону иштетпей турсаңыз деле, ал такай организмдин негизги көрсөткүчтөрү тууралуу cенсордун дайындарын жаздыра алат. Муну өзгөртүү үчүн "<annotation id="link">"жөндөөлөргө өтүңүз."</annotation></string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
+ <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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Бул колдонмого дене сенсорлорунун көрсөткүчтөрүн көрүү мүмкүнчүлүгүн берүү үчүн (колдонмо колдонулбай турганда да) "<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="auto_granted_permissions" msgid="6009452264824455892">"Көзөмөлдөнгөн уруксаттар"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сизге билдирмелерди жөнөтүүгө уруксат бересизби?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Көзөмөлдөнгөн уруксаттар"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> жүргөн жериңизди аныктай алат"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Уюмуңуз <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосуна жүргөн жериңизди аныктоого уруксат берет"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Башка уруксаттар"</string>
- <string name="not_used_permissions_label" msgid="3939839426115141264">"Тутум пайдаланган уруксат"</string>
+ <string name="not_used_permissions_label" msgid="3939839426115141264">"Система пайдаланган уруксат"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Системанын колдонмолору гана пайдаланган уруксаттар."</string>
<string name="additional_permissions_label" msgid="7693557637462569046">"Кошумча уруксаттар"</string>
<string name="additional_permissions_description" msgid="2186611950890732112">"Колдонмолор аныктаган уруксаттар."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Бул колдонмо жайгашкан жер тууралуу маалыматты үчүнчү тараптар менен бөлүшүүгө уруксат сурап жатат"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Маалыматты бөлүшүү жана турган жер"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Бөлүшүп жаткан нерселер кайдан алынат"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Иштеп чыгуучу бул колдонмо маалыматтарды кантип бөлүшкөнүн түзмөктүн өндүрүүчүсүнө билдирди. Иштеп чыгуучу бул маалыматты кийинчерээк жаңыртып турушу мүмкүн."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Иштеп чыгуучу бул колдонмо маалыматтарды кантип бөлүшкөнүн төмөнкүгө билдирди: "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Иштеп чыгуучу бул маалыматты жаңыртып турушу мүмкүн."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Бул колдонмо турган жериңиз тууралуу маалыматты төмөнкүлөр үчүн бөлүшүшү мүмкүн:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Маалымат ар кандай жолдор менен бөлүшүлөт"</string>
@@ -608,12 +661,10 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Маалыматтардын коопсуздугу"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Турган жериңиз тууралуу маалымат бөлүшүлүп жатышы мүмкүн"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Бул колдонмо турган жериңиз тууралуу маалыматты үчүнчү тараптар менен бөлүшүүсү мүмкүн"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Бул шилтемени ачууга болбойт"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Турган жериңизди билдирүү ыкмасын жаңыртуу"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Жүргөн жериңизди көрсөткөн ыкманы өзгөрткөн колдонмолорду карап чыксаңыз болот"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Бул колдонмолор жүргөн жериңиз тууралуу маалыматты бөлүшүү ыкмасын өзгөрттү. Алар бул маалыматты мурда бөлүшпөй же азыр жарнамалоо же маркетинг максаттарында бөлүшүшү мүмкүн."</string>
- <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Бул колдонмолорду иштеп чыгуучулар дайын-даректерди бөлүшүү тууралуу маалыматты колдонмолор дүкөнүнө беришти. Алар бул маалыматты жаңыртып турушу мүмкүн.\n\nМаалыматтарды бөлүшүү ыкмасы колдонмонун версиясына, колдонулушуна, регионго жана курагыңызга жараша айырмаланышы мүмкүн."</string>
+ <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Бул колдонмолорду иштеп чыгуучулар нерселерди бөлүшүү тууралуу маалыматты колдонмолор дүкөнүнө беришти. Алар бул маалыматты жаңыртып турушу мүмкүн.\n\nМаалыматтарды бөлүшүү ыкмасы колдонмонун версиясына, колдонулушуна, регионго жана курагыңызга жараша айырмаланышы мүмкүн."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Маалыматтарды бөлүшүү жөнүндө кеңири маалымат"</string>
<string name="shares_location_with_third_parties" msgid="2278051743742057767">"Жүргөн жериңиз тууралуу маалымат үчүнчү тараптар менен бөлүшүлүп жатат"</string>
<string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"Жүргөн жериңизди үчүнчү тараптар жарнамалоо же маркетинг максатында билип турушат"</string>
diff --git a/PermissionController/res/values-lo-v33/strings.xml b/PermissionController/res/values-lo-v33/strings.xml
index 50beda6aa..743a5bec9 100644
--- a/PermissionController/res/values-lo-v33/strings.xml
+++ b/PermissionController/res/values-lo-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ແຈ້ງເຕືອນເພີ່ມເຕີມ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ປິດການແຈ້ງເຕືອນແລ້ວ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ຂະຫຍາຍ ແລະ ເບິ່ງແຈ້ງເຕືອນເພີ່ມອີກ 1 ລາຍການ}other{ຂະຫຍາຍ ແລະ ເບິ່ງແຈ້ງເຕືອນເພີ່ມອີກ # ລາຍການ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ແຈ້ງເຕືອນ. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ຄຳສັ່ງສຳເລັດ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ກວດເບິ່ງການຕັ້ງຄ່າທີ່ສາມາດເພີ່ມການປ້ອງກັນໃຫ້ກັບອຸປະກອນຂອງທ່ານ"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"ການຕັ້ງຄ່າດ່ວນຄວາມປອດໄພ ແລະ ຄວາມເປັນສ່ວນຕົວ"</string>
diff --git a/PermissionController/res/values-lo/strings.xml b/PermissionController/res/values-lo/strings.xml
index 083819bf5..9b8792697 100644
--- a/PermissionController/res/values-lo/strings.xml
+++ b/PermissionController/res/values-lo/strings.xml
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"ສະແດງການກວດຫາຕົວເປີດຜູ້ຊ່ວຍ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ສະແດງໄອຄອນໃນແຖບສະຖານະເມື່ອໃຊ້ໄມໂຄຣໂຟນເພື່ອເປີດໃຊ້ຜູ້ຊ່ວຍແບບສຽງ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຮູບພາບ ແລະ ມີເດຍຢູ່ອຸປະກອນຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງລາຍຊື່ຜູ້ຕິດຕໍ່ຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງສະຖານທີ່ຂອງອຸປະກອນບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ແອັບຈະມີສິດເຂົ້າເຖິງສະຖານທີ່ໃນເວລາທີ່ທ່ານກຳລັງໃຊ້ແອັບຢູ່ເທົ່ານັ້ນ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງສະຖານທີ່ຂອງອຸປະກອນບໍ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ແອັບນີ້ອາດຕ້ອງການເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"ປ່ຽນສິດອະນຸຍາດເຂົ້າເຖິງສຳລັບ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ແອັບນີ້ຕ້ອງການເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ຊອກຫາ, ເຊື່ອມຕໍ່ຫາ ແລະ ກຳນົດຕຳແໜ່ງທີ່ກ່ຽວຂ້ອງກັນຂອງອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ຊອກຫາ, ເຊື່ອມຕໍ່ຫາ ແລະ ກຳນົດຕຳແໜ່ງທີ່ກ່ຽວຂ້ອງກັນຂອງອຸປະກອນທີ່ຢູ່ໃກ້ຄຽງບໍ? "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"ປ່ຽນການເຂົ້າເຖິງສະຖານທີ່ຂອງ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ຈາກໂດຍປະມານເປັນແບບລະອຽດບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານຂອງອຸປະກອນນີ້ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ແບບລະອຽດ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ໂດຍປະມານ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງປະຕິທິນຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ສົ່ງ ແລະ ອ່ານຂໍ້ຄວາມ SMS ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຮູບພາບ, ມີເດຍ ແລະ ໄຟລ໌ຢູ່ອຸປະກອນຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງ &lt;b&gt;ຮູບພາບ, ວິດີໂອ, ເພງ ແລະ ສຽງ&lt;/b&gt; ຢູ່ອຸປະກອນນີ້ບໍ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງ &lt;b&gt;ຮູບພາບ, ວິດີໂອ, ເພງ, ສຽງ ແລະ ໄຟລ໌ອື່ນໆ&lt;/b&gt; ຢູ່ອຸປະກອນນີ້ບໍ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງເພງ ແລະ ສຽງຢູ່ອຸປະກອນນີ້ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງຮູບພາບ ແລະ ວິດີໂອຢູ່ອຸປະກອນນີ້ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງຮູບພາບ ແລະ ວິດີໂອເພີ່ມເຕີມຢູ່ອຸປະກອນນີ້ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ບັນທຶກສຽງບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ແອັບນີ້ສາມາດບັນທຶກສຽງໃນຂະນະທີ່ທ່ານກຳລັງໃຊ້ແອັບເທົ່ານັ້ນ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ບັນທຶກສຽງບໍ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ແອັບນີ້ອາດຕ້ອງການບັນທຶກສຽງຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"ປ່ຽນສິດເຂົ້າເຖິງໄມໂຄຣໂຟນສຳລັບ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ແອັບນີ້ຕ້ອງການບັນທຶກສຽງຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງກິດຈະກຳທາງກາຍະພາບຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ແອັບຈະສາມາດຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອໄດ້ສະເພາະໃນເວລາທີ່ທ່ານກຳລັງໃຊ້ແອັບເທົ່ານັ້ນ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອບໍ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ແອັບນີ້ອາດຕ້ອງການຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"ປ່ຽນສິດເຂົ້າເຖິງກ້ອງສຳລັບ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ແອັບອາດຕ້ອງການຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ໃຊ້ແອັບຢູ່ກໍຕາມ. "<annotation id="link">"ອະນຸຍາດໃນການຕັ້ງຄ່າ."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ເຂົ້າເຖິງບັນທຶກການໂທທັງໝົດຂອງທ່ານໄດ້ບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ໂທ ແລະ ຈັດການການໂທບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີກ່ຽວກັບສັນຍານຊີບຂອງທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ເພື່ອເຮັດໃຫ້ແອັບນີ້ເຂົ້າເຖິງຂໍ້ມູນເຊັນເຊີຮ່າງກາຍໄດ້ຕະຫຼອດເວລາ, ເຖິງແມ່ນວ່າທ່ານຈະບໍ່ໄດ້ກຳລັງໃຊ້ແອັບຢູ່ກໍຕາມ, "<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="auto_granted_permissions" msgid="6009452264824455892">"ສິດອະນຸຍາດທີ່ມີການຄວບຄຸມ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ສົ່ງການແຈ້ງເຕືອນຫາທ່ານບໍ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"ສິດອະນຸຍາດທີ່ມີການຄວບຄຸມ"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ມີສິດເຂົ້າເຖິງສະຖານທີ່"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ອົງກອນຂອງທ່ານອະນຸຍາດ <xliff:g id="APP_NAME">%1$s</xliff:g> ໃຫ້ເຂົ້າເຖິງສະຖານທີ່ຂອງທ່ານ"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"ການອະນຸຍາດອື່ນໆ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"ການອະນຸຍາດທີ່ໃຊ້ໂດຍລະບົບ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"ການອະນຸຍາດທີ່ໃຊ້ໂດຍແອັບພລິເຄຊັນລະບົບເທົ່ານັ້ນ."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ແອັບນີ້ລະບຸວ່າມັນອາດແບ່ງປັນຂໍ້ມູນສະຖານທີ່ກັບພາກສ່ວນທີສາມ"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ການແບ່ງປັນຂໍ້ມູນ ແລະ ສະຖານທີ່"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ແຫຼ່ງທີ່ມາຂອງລາຍລະອຽດການແບ່ງປັນຂໍ້ມູນ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ນັກພັດທະນາແອັບໄດ້ໃຫ້ຂໍ້ມູນກັບຜູ້ຜະລິດອຸປະກອນນີ້ກ່ຽວກັບວິທີທີ່ແອັບນີ້ແບ່ງປັນຂໍ້ມູນ. ນັກພັດທະນາແອັບອາດອັບເດດຂໍ້ມູນນີ້ເມື່ອເວລາຜ່ານໄປ."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ນັກພັດທະນາແອັບໄດ້ໃຫ້ຂໍ້ມູນໄວ້ໃນ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" ກ່ຽວກັບວິທີທີ່ແອັບນີ້ແບ່ງປັນຂໍ້ມູນ. ນັກພັດທະນາອາດອັບເດດຂໍ້ມູນນີ້ເມື່ອເວລາຜ່ານໄປ."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ແອັບນີ້ອາດແບ່ງປັນຂໍ້ມູນສະຖານທີ່ຍ້ອນ:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ການແບ່ງປັນຂໍ້ມູນອາດແຕກຕ່າງກັນໄປ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ຄວາມປອດໄພຂອງຂໍ້ມູນ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ອາດມີການແບ່ງປັນຂໍ້ມູນສະຖານທີ່"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ແອັບນີ້ລະບຸວ່າມັນອາດແບ່ງປັນຂໍ້ມູນສະຖານທີ່ກັບພາກສ່ວນທີສາມ"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ບໍ່ສາມາດເປີດລິ້ງນີ້ໄດ້"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ການອັບເດດການແບ່ງປັນຂໍ້ມູນສະຖານທີ່"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ກວດສອບແອັບທີ່ປ່ຽນແປງວິທີທີ່ແອັບອາດແບ່ງປັນຂໍ້ມູນສະຖານທີ່ຂອງທ່ານ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ແອັບເຫຼົ່ານີ້ໄດ້ປ່ຽນແປງວິທີທີ່ແອັບອາດແບ່ງປັນຂໍ້ມູນສະຖານທີ່ຂອງທ່ານແລ້ວ. ແອັບເຫຼົ່ານີ້ອາດບໍ່ເຄີຍແບ່ງປັນຂໍ້ມູນມາກ່ອນ ຫຼື ອາດແບ່ງປັນຂໍ້ມູນເພື່ອຈຸດປະສົງໃນການໂຄສະນາ ຫຼື ການຕະຫຼາດ."</string>
diff --git a/PermissionController/res/values-lt-v33/strings.xml b/PermissionController/res/values-lt-v33/strings.xml
index b4cfa2a91..41c3bdc9f 100644
--- a/PermissionController/res/values-lt-v33/strings.xml
+++ b/PermissionController/res/values-lt-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Daugiau įspėjimų"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Atsisakyta įspėjimų"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Išskleiskite ir peržiūrėkite dar vieną įspėjimą}one{Išskleiskite ir peržiūrėkite dar # įspėjimą}few{Išskleiskite ir peržiūrėkite dar # įspėjimus}many{Išskleiskite ir peržiūrėkite dar # įspėjimo}other{Išskleiskite ir peržiūrėkite dar # įspėjimų}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Įspėjimas. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Veiksmas atliktas"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Patikrinkite nustatymus, kuriuos taikant galima užtikrinti papildomą įrenginio apsaugą"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Spartieji saugos ir privatumo nustatymai"</string>
diff --git a/PermissionController/res/values-lt/strings.xml b/PermissionController/res/values-lt/strings.xml
index 81f670ff3..79851dcef 100644
--- a/PermissionController/res/values-lt/strings.xml
+++ b/PermissionController/res/values-lt/strings.xml
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Paskutinį kartą atidaryta <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Jei leisite valdyti visus failus, ši programa galės pasiekti, keisti ir ištrinti bet kuriuos failus, esančius šio įrenginio bendroje saugykloje arba susietų saugyklų įrenginiuose. Programa gali pasiekti failus nepaklaususi."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Leisti šiai programai pasiekti, keisti ir ištrinti failus, esančius šiame įrenginyje ar bet kuriuose susietų saugyklų įrenginiuose? Ši programa gali pasiekti failus nepaklaususi."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Programos, kurioms suteiktas šis leidimas, gali <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Programos, kurioms suteiktas šis leidimas, gali: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Programos, kurioms suteiktas šis leidimas, gali pasiekti jūsų fizinę veiklą, pvz., ėjimą, važiavimą dviračiu, vairavimą, žingsnių skaičių ir daugiau"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Programos, kurioms suteiktas šis leidimas, gali pasiekti jūsų kalendorių"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Programos, kurioms suteiktas šis leidimas, gali skaityti ir rašyti telefono skambučių žurnalą"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Rodyti padėjėjo aktyviklio aptikimą"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Rodyti piktogramą būsenos juostoje, kai naudojant mikrofoną aktyvinama pagalba balsu"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti įrenginio nuotraukas ir mediją?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti kontaktus?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti įrenginio vietovę?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Programa galės pasiekti vietovę, tik kai ją naudosite"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti įrenginio vietovę?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ši programa gali norėti pasiekti jūsų vietovę visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Pakeisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie vietovės duomenų?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ši programa nori pasiekti jūsų vietovę visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; rasti netoliese esančius įrenginius, prisijungti prie jų ir nustatyti apytikslį atstumą?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; rasti netoliese esančius įrenginius, prisijungti prie jų ir nustatyti apytikslį atstumą? "<annotation id="link">"Leiskite nustatymuose."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Pakeisti <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> vietovės pasiekiamumą iš apytikslės į tikslią?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti apytikslę šio įrenginio vietovę?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Tiksli"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Apytikslė"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti kalendorių?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; siųsti ir peržiūrėti SMS pranešimus?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Suteikti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; galimybę pasiekti įrenginio nuotraukas, mediją ir failus?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti &lt;b&gt;nuotraukas, vaizdo, garso įrašus ir muziką&lt;/b&gt; šiame įrenginyje?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti &lt;b&gt;nuotrauk., vaizdo, garso įrašus, muziką, kitus failus&lt;/b&gt; įrenginyje?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti muziką ir garso failus šiame įrenginyje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti nuotraukas ir vaizdo įrašus šiame įrenginyje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti nuotraukas ir vaizdo įrašus šiame įrenginyje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; įrašyti garsą?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Programa galės įrašyti garsą, tik kai ją naudosite"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; įrašyti garsą?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ši programa gali norėti įrašyti garsą visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Pakeisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie mikrofono?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ši programa nori įrašyti garsą visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pasiekti fizinės veiklos duomenis?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotografuoti ir įrašyti vaizdo įrašus?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Programa galės fotografuoti ir įrašyti vaizdo įrašų, tik kai ją naudosite"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotografuoti ir įrašyti vaizdo įrašus?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ši programa gali norėti fotografuoti ir įrašyti vaizdo įrašų visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Pakeisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prieigą prie fotoaparato?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ši programa nori fotografuoti ir įrašyti vaizdo įrašų visą laiką, net kai programos nenaudojate. "<annotation id="link">"Leiskite skiltyje „Nustatymai“."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Valdomi leidimai"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Valdomi leidimai"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ gali pasiekti vietovę"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Jūsų organizacija leidžia programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“ pasiekti jūsų vietovę"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Kiti leidimai"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Leidimai, kuriuos naudoja sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Leidimai, kuriuos naudoja tik sistemos programos."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ši programa nurodė, kad gali bendrinti vietovės duomenis su trečiosiomis šalimis"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Duomenų bendrinimas ir vietovė"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Iš kur gaunama duomenų bendrinimo informacija"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Kūrėjas pateikė informacijos šio įrenginio gamintojui apie tai, kaip ši programa bendrina duomenis. Bėgant laikui kūrėjas gali atnaujinti šią informaciją."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Kūrėjas pateikė informacijos "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" apie duomenų bendrinimą šioje programoje. Bėgant laikui kūrėjas gali atnaujinti šią informaciją."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ši programa gali bendrinti vietovės duomenis dėl:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Duomenų bendrinimas skiriasi"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Duomenų sauga"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Vietovės duomenys gali būti bendrinami"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ši programa nurodė, kad gali bendrinti vietovės duomenis su trečiosiomis šalimis"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Šios nuorodos atidaryti nepavyko"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Duomenų bendrinimo atnaujinimai pagal vietovę"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Peržiūrėkite programas, kuriose pakeisti vietovės duomenų bendrinimo metodai"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Šiose programose pakeisti vietovės duomenų bendrinimo metodai Gali būti, kad anksčiau jie nebuvo bendrinami, arba dabar jie gali būti bendrinami reklamavimo ar rinkodaros tikslais."</string>
diff --git a/PermissionController/res/values-lv-v33/strings.xml b/PermissionController/res/values-lv-v33/strings.xml
index c935b9cee..825ac7aec 100644
--- a/PermissionController/res/values-lv-v33/strings.xml
+++ b/PermissionController/res/values-lv-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Citi brīdinājumi"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Noraidītie brīdinājumi"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Izvērsiet un skatiet vēl vienu brīdinājumu.}zero{Izvērsiet un skatiet vēl # brīdinājumus.}one{Izvērsiet un skatiet vēl # brīdinājumu.}other{Izvērsiet un skatiet vēl # brīdinājumus.}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Brīdinājums. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Darbība ir pabeigta"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Pārbaudiet iestatījumus, kas var uzlabot ierīces aizsardzību"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Drošības un konfidencialitātes ātrie iestatījumi"</string>
diff --git a/PermissionController/res/values-lv/strings.xml b/PermissionController/res/values-lv/strings.xml
index 90cb29e3b..636d2b869 100644
--- a/PermissionController/res/values-lv/strings.xml
+++ b/PermissionController/res/values-lv/strings.xml
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Rādīt asistenta aktivizētāja noteikšanu"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Rādīt ikonu statusa joslā, kad mikrofons tiek izmantots balss palīga aktivizēšanai"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt fotoattēliem un multivides saturam jūsu ierīcē?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu kontaktpersonām?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt šīs ierīces atrašanās vietai?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Lietotne varēs piekļūt atrašanās vietai tikai tad, kad izmantosiet šo lietotni"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt šīs ierīces atrašanās vietai?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Iespējams, šī lietotne vēlēsies piekļūt jūsu atrašanās vietai vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vai mainīt lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļuvi atrašanās vietai?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Šī lietotne vēlas piekļūt jūsu atrašanās vietai vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Vai atļaut &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; atrast tuvumā esošas ierīces, veidot savienojumus ar tām un noteikt to relatīvo atrašanās vietu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Vai atļaut &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; atrast tuvumā esošas ierīces, veidot savienojumus ar tām un noteikt to relatīvo atrašanās vietu? "<annotation id="link">"Varat to atļaut iestatījumos."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Vai mainīt lietotnes <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> piekļuvi atrašanās vietai no aptuvenās uz precīzo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt aptuvenai šīs ierīces atrašanās vietai?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Precīza"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aptuvena"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu kalendāram?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sūtīt un skatīt īsziņas?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt fotoattēliem, multivides saturam un failiem jūsu ierīcē?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt &lt;b&gt;foto, video, mūzikai un audio failiem&lt;/b&gt; šajā ierīcē?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt &lt;b&gt;foto, video, mūzikai, audio u.c. failiem&lt;/b&gt; ierīcē?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt mūzikai un audio failiem šajā ierīcē?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt fotoattēliem un video šajā ierīcē?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt citiem fotoattēliem un video šajā ierīcē?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ierakstīt audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Lietotne varēs ierakstīt audio tikai tad, kad izmantosiet lietotni."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ierakstīt audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Iespējams, šī lietotne vēlēsies ierakstīt audio vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vai mainīt lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļuvi mikrofonam?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Šī lietotne vēlas ierakstīt audio vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļūt jūsu fiziskajām aktivitātēm?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uzņemt fotoattēlus un ierakstīt videoklipus?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Lietotne varēs uzņemt attēlus un ierakstīt videoklipus tikai tad, kad izmantosiet lietotni."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uzņemt fotoattēlus un ierakstīt videoklipus?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Iespējams, šī lietotne vēlēsies uzņemt attēlus un ierakstīt videoklipus vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vai mainīt lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; piekļuvi kamerai?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Šī lietotne vēlas uzņemt attēlus un ierakstīt videoklipus vienmēr, pat ja neizmantojat lietotni. "<annotation id="link">"Atļauju varat piešķirt iestatījumos."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrolētās atļaujas"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrolētās atļaujas"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> ir piekļuve atrašanās vietai"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Jūsu organizācija ļauj lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g> piekļūt jūsu atrašanās vietai."</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Citas atļaujas"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Sistēmas izmantotās atļaujas"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Atļaujas, kas tiek izmantotas tikai sistēmas lietojumprogrammās."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Lietotne norādīja, ka tā var kopīgot atrašanās vietas datus ar trešajām pusēm."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datu kopīgošana un atrašanās vieta"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Datu kopīgošanas informācijas avots"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Izstrādātājs sniedza ierīces ražotājam informāciju par to, kā šajā lietotnē tiek kopīgoti dati. Laika gaitā izstrādātājs var šo informāciju atjaunināt."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Izstrādātājs sniedza lietotņu veikalam "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" informāciju par to, kā šajā lietotnē tiek kopīgoti dati. Laika gaitā izstrādātājs var šo informāciju atjaunināt."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Atrašanās vietas datu kopīgošanas nolūki lietotnē"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datu kopīgošana var atšķirties"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datu drošība"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Atrašanās vietas dati var tikt kopīgoti"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Lietotne norādīja, ka tā var kopīgot atrašanās vietas datus ar trešajām pusēm."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Nevar atvērt šo saiti"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Atjauninājumi atrašanās vietas datu kopīgošanā"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Pārskatiet lietotnes, kurās ir mainīti atrašanās vietas datu kopīgošanas veidi."</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Šajās lietotnēs ir mainīti atrašanās vietas datu kopīgošanas veidi. Varbūt tās iepriekš nekopīgoja šādus datus, bet varbūt tagad tos kopīgo reklamēšanas vai mārketinga nolūkos."</string>
diff --git a/PermissionController/res/values-mk-v33/strings.xml b/PermissionController/res/values-mk-v33/strings.xml
index deb8f25e7..95896fb8e 100644
--- a/PermissionController/res/values-mk-v33/strings.xml
+++ b/PermissionController/res/values-mk-v33/strings.xml
@@ -30,10 +30,9 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Повеќе предупредувања"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Отфрлени известувања"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Проширете и видете уште едно предупредување}one{Проширете и видете уште # предупредување}other{Проширете и видете уште # предупредувањa}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Предупредување. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Дејството е завршено"</string>
- <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Брзи поставки што може да додадат заштита на вашиот уред"</string>
+ <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Прегледајте ги поставките со кои може дополнително да го заштитите уредот"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Брзи поставки за безбедност и приватност"</string>
<string name="safety_center_qs_close_button" msgid="1352313308176244599">"Затвори"</string>
<string name="safety_center_qs_expand_action" msgid="2193190557696484169">"Прошири и прикажи ги опциите"</string>
diff --git a/PermissionController/res/values-mk-v34/strings.xml b/PermissionController/res/values-mk-v34/strings.xml
index d3483f90e..e8f9afc25 100644
--- a/PermissionController/res/values-mk-v34/strings.xml
+++ b/PermissionController/res/values-mk-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Безбедност и приватност"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Контроли"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Управувајте со пристапот на апликацијата до здравствените податоци"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Управувајте со пристапот на апликациите до здравствените податоци"</string>
<string name="location_settings" msgid="8863940440881290182">"Пристап до локацијата"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"За апликации и услуги. Ако поставкава е исклучена, податоците за микрофонот може сепак да се споделат кога ќе се јавите на број за итни случаи"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"За апликации и услуги. Ако поставкава е исклучена, податоците од микрофонот може сепак да се споделат кога ќе се јавите на број за итни случаи"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"За апликации и услуги"</string>
</resources>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index ed2153549..164d6f2e9 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name" msgid="6098036489833144040">"Permission controller"</string>
+ <string name="app_name" msgid="6098036489833144040">"Управувач со дозволи"</string>
<string name="ok" msgid="1936281769725676272">"Во ред"</string>
<string name="permission_search_keyword" msgid="1214451577494730543">"дозволи"</string>
<string name="cancel" msgid="8943320028373963831">"Откажи"</string>
@@ -32,9 +32,9 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"Задржи ја „Додека се користи апликацијата“"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"Задржи „Само овој пат“"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Уште информации"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Дозволи ги сите"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Дозволи за сите"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Секогаш дозволувај ги сите"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Изберете фотографии и видеа"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Одредени фотографии и видеа"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Изберете повеќе"</string>
<string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Не избирајте повеќе"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Сепак не дозволувај"</string>
@@ -84,7 +84,7 @@
<string name="app_permissions_group_summary" msgid="8788419008958284002">"Апликации со дозвола: <xliff:g id="COUNT_0">%1$d</xliff:g> од <xliff:g id="COUNT_1">%2$d</xliff:g>"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"<xliff:g id="COUNT_0">%1$d</xliff:g>/<xliff:g id="COUNT_1">%2$d</xliff:g> дозволени апликации"</string>
<string name="menu_show_system" msgid="4254021607027872504">"Прикажи го системот"</string>
- <string name="menu_hide_system" msgid="3855390843744028465">"Сокриј го системот"</string>
+ <string name="menu_hide_system" msgid="3855390843744028465">"Скриј го системот"</string>
<string name="menu_show_7_days_data" msgid="8979611198508523706">"Прикажи 7 дена"</string>
<string name="menu_show_24_hours_data" msgid="8228054833323380780">"Прикажи 24 часа"</string>
<string name="manage_permission" msgid="2895385393037061964">"Управувајте со дозволата"</string>
@@ -129,7 +129,7 @@
<string name="permission_group_usage_title" msgid="2595013198075285173">"Користење <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Видете други дозволи"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
- <string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> и уште <xliff:g id="NUM">%3$s</xliff:g> други"</string>
+ <string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> и уште <xliff:g id="NUM">%3$s</xliff:g>"</string>
<string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Кога ја користеле апликациите дозволата за <xliff:g id="PERMGROUP">%1$s</xliff:g> во минатите 24 часа"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"Кога ја користеле апликациите дозволата за <xliff:g id="PERMGROUP">%1$s</xliff:g> во минатите 7 дена"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"Кога апликацијава ја користела дозволата за <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
@@ -219,7 +219,7 @@
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"Дозволите за „<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g>“ и „<xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g>“ се отстранети"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"Дозволата за „<xliff:g id="PERMISSION_NAME">%1$s</xliff:g>“ и уште <xliff:g id="NUMBER">%2$s</xliff:g> други дозволи се отстранети"</string>
<string name="unused_apps_page_title" msgid="6986983535677572559">"Некористени апликации"</string>
- <string name="unused_apps_page_summary" msgid="1867593913217272155">"Ако некоја апликација не се користи неколку месеци:\n\n• дозволите се отстрануваат за да се заштитат вашите податоци\n• известувањата се стопираат за да се заштеди батерија\n• привремените датотеки се отстрануваат за да се ослободи простор\n\nЗа да повторно се овозможат дозволите и известувањата, отворете ја апликацијата."</string>
+ <string name="unused_apps_page_summary" msgid="1867593913217272155">"Ако некоја апликација не се користи неколку месеци:\n\n• дозволите се отстрануваат за да се заштитат вашите податоци\n• известувањата се стопираат за да се заштеди батерија\n• привремените датотеки се отстрануваат за да се ослободи простор\n\nЗа повторно да се овозможат дозволите и известувањата, отворете ја апликацијата."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Ако некоја апликација не се користи еден месец:\n\n• дозволите се отстрануваат за да се заштитат вашите податоци\n• привремените датотеки се отстрануваат за да се ослободи простор\n\nЗа да ги овозможите дозволите повторно, отворете ја апликацијата."</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Последно отворени пред повеќе од # месец}one{Последно отворени пред повеќе од # месец}other{Последно отворени пред повеќе од # месеци}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"Последно отворање на апликацијата: <xliff:g id="DATE">%s</xliff:g>"</string>
@@ -273,7 +273,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>
- <string name="go_to_settings" msgid="1053735612211228335">"Одете во „Поставки“"</string>
+ <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>
@@ -306,7 +306,7 @@
<string name="unused_apps_subtitle_after" msgid="2034267519506357898">"Дозволите се отстранети од"</string>
<string name="unused_apps_subtitle_before" msgid="5233302577076132427">"Дозволите ќе се отстранат од"</string>
<string name="unused_permissions_subtitle_two" msgid="2207266295008423015">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g> и <xliff:g id="PERM_NAME_1">%2$s</xliff:g>"</string>
- <string name="unused_permissions_subtitle_many" msgid="4387289202207450238">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g>, <xliff:g id="PERM_NAME_1">%2$s</xliff:g> и уште <xliff:g id="NUMBER_OF_PERMISSIONS">%3$s</xliff:g> други"</string>
+ <string name="unused_permissions_subtitle_many" msgid="4387289202207450238">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g>, <xliff:g id="PERM_NAME_1">%2$s</xliff:g> и уште <xliff:g id="NUMBER_OF_PERMISSIONS">%3$s</xliff:g>"</string>
<string name="unused_app_permissions_removed_summary" msgid="6779039455326071033">"За заштита на податоците, отстранети се дозволите од апликациите што не сте ги користеле неколку месеци"</string>
<string name="unused_app_permissions_removed_summary_some" msgid="5080490037831563441">"За заштита на податоците, отстранети се дозволите од некои апликации што не сте ги користеле неколку месеци."</string>
<string name="one_unused_app_summary" msgid="7831913934488881991">"1 апликација не е користена неколку месеци"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Прикажувај го откривањето за активирање на помошникот"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Прикажувај икона во статусната лента кога микрофонот се користи за активирање на гласовниот помошник"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до фотографии и аудиовизуелни содржини на уредот?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до контактите?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до локацијата на уредов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Апликацијата ќе има пристап до локацијата само додека ја користите"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до локацијата на уредов?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Апликацијава можеби ќе сака да пристапува до вашата локација цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во поставките."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Да се промени пристапот до локацијата за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Апликацијава сака да пристапува до вашата локација цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во поставките."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да наоѓа и да се поврзува со уреди во близина и да ја утврдува нивната релативна положба?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да наоѓа и да се поврзува со уреди во близина и да ја утврдува нивната релативна положба? "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Да се промени пристапот до локацијата на <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> од приближна на прецизна?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до приближната локација на уредов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Прецизна"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Приближна"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до календарот?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да испраќа и прегледува SMS-пораки?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до фотографиите, аудиовизуелните содржини и датотеките на уредот?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до &lt;b&gt;фотографии, видеа, музика и аудио&lt;/b&gt; на уредов?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до &lt;b&gt;фотографии, видеа, музика, аудио и други датотеки&lt;/b&gt; на уредов?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до музика и аудиодатотеки на уредов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до фотографии и видеа на уредов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до повеќе фотографии и видеа на уредов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да снима аудио?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Апликацијава ќе може да снима аудио само додека ја користите"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да снима аудио?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Апликацијава можеби ќе сака да снима аудио цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Да се промени пристапот до микрофонот за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Апликацијава сака да снима аудио цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Дозволувате ли &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до вашата физичка активност?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да фотографира и да снима видео?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Апликацијава ќе може да снима слики и видеа само додека ја користите"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да фотографира и да снима видео?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Апликацијава можеби ќе сака да снима слики и видеа цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Да се промени пристапот до камерата за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Апликацијава сака да снима слики и видеа цело време, дури и кога не ја користите. "<annotation id="link">"Дозволете во „Поставки“."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
+ <string name="permgrouprequest_phone" msgid="1829234136997316752">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да упатува телефонски повици и да управува со нив?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да пристапува до податоците на сензорот за витални знаци?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"За да дозволите апликацијава да пристапува до податоци од телесните сензори цело време, дури и кога не ја користите, "<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="auto_granted_permissions" msgid="6009452264824455892">"Контролирани дозволи"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да ви испраќа известувања?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Контролирани дозволи"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> има пристап до локацијата"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Вашата организација дозволува <xliff:g id="APP_NAME">%1$s</xliff:g> да пристапува до вашата локација"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Други дозволи"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Дозволи што ги користи системот"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Дозволи што ги користат само системските апликации."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Апликацијава изјави дека можеби ќе споделува податоци за локацијата со трети страни"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Споделување податоци и локација"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Од каде доаѓаат информациите за споделувањето податоци"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Програмерот доставил информации до производителот на уредов за начинот на кој апликацијава споделува податоци. Програмерот може да ги ажурира информацииве со текот на времето."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Програмерот доставил информации до "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" за начинот на кој апликацијава споделува податоци. Програмерот може да ги ажурира податоциве со текот на времето."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Апл. може да споделува податоци за локацијата за:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Споделувањето податоци варира"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Безбедност на податоците"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Можно е да се споделуваат податоците за локација"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Апликацијава наведе дека можеби ќе ги споделува вашите податоци за локацијата со трети страни"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Не може да се отвори линков"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Промени во споделувањето на податоците за локација"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Прегледајте ги апликациите што го промениле начинот на кој може да ги споделуваат вашите податоци за локација"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Овие апликации го промениле начинот на кој може да ги споделуваат вашите податоци за локација. Претходно можеби не ги споделувале или можеби сега ги споделуваат во рекламни или маркетиншки цели."</string>
diff --git a/PermissionController/res/values-ml/strings.xml b/PermissionController/res/values-ml/strings.xml
index 581ff9938..9136b148c 100644
--- a/PermissionController/res/values-ml/strings.xml
+++ b/PermissionController/res/values-ml/strings.xml
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"അസിസ്‌റ്റന്റ് ട്രിഗർ കണ്ടെത്തൽ കാണിക്കുക"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ശബ്‌ദ സഹായം സജീവമാക്കാൻ മൈക്രോഫോൺ ഉപയോഗിക്കുമ്പോൾ സ്റ്റാറ്റസ് ബാറിൽ ഐക്കൺ കാണിക്കുക"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"നിങ്ങളുടെ ഉപകരണത്തിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിലെ ഫോട്ടോകളും മീഡിയയും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"നിങ്ങളുടെ കോണ്‍ടാക്റ്റുകള്‍ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ നിങ്ങളുടെ കോൺടാക്‌റ്റുകൾ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt; എന്നതിന്റെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കുമ്പോൾ മാത്രമേ അതിന് ലൊക്കേഷൻ ആക്‌സസ് ലഭിക്കൂ."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ഈ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g> എന്നതിന്റെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും, എല്ലാ സമയത്തും ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യേണ്ടതുണ്ട്. "<annotation id="link">"ക്രമീകരണത്തിൽ"</annotation>" അനുവദിക്കുക."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിന്റെ ലൊക്കേഷൻ ആക്സസ് മാറ്റണോ?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനുള്ള ലൊക്കേഷൻ ആക്‌സസ് മാറ്റണോ?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ആപ്പ് നിങ്ങൾ ഉപയോഗിക്കാത്തപ്പോഴടക്കം, എല്ലാ സമയത്തും ഈ ആപ്പ് നിങ്ങളുടെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"സമീപത്തെ ഉപകരണങ്ങൾ കണ്ടെത്താനും കണക്റ്റ് ചെയ്യാനും ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ സമീപ ഉപകരണം കണ്ടെത്താനും കണക്റ്റ് ചെയ്യാനും ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; -നെ അനുവദിക്കണോ?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"സമീപത്തെ ഉപകരണങ്ങൾ കണ്ടെത്തി കണക്റ്റ് ചെയ്ത് ആപേക്ഷിക സ്ഥാനം നിർണ്ണയിക്കാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ? "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> എന്നതിന്റെ ലൊക്കേഷൻ ആക്‌സസ് \'ഏകദേശം\' എന്നതിൽ നിന്ന് \'കൃത്യമായത്\' എന്നതിലേക്ക് മാറ്റണോ?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ആപ്പിന്റെ ലൊക്കേഷൻ ആക്‌സസ്, ഏകദേശം എന്നതിൽ നിന്ന് കൃത്യം എന്നതായി മാറ്റണോ?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ഈ ഉപകരണത്തിന്റെ ഏകദേശ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിന്റെ ഏകദേശ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"കൃത്യമായത്"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ഏകദേശം"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"നിങ്ങളുടെ കലണ്ടർ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ നിങ്ങളുടെ കലണ്ടർ ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS സന്ദേശങ്ങൾ അയയ്ക്കാനും കാണാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ SMS സന്ദേശങ്ങൾ അയയ്ക്കാനും കാണാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"നിങ്ങളുടെ ഉപകരണത്തിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിലെ ഫോട്ടോകളും മീഡിയയും ഫയലുകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ഇതിലെ &lt;/b&gt;ഫോട്ടോകൾ, വീഡിയോ, സംഗീതം, ഓഡിയോ&lt;/b&gt; എന്നിവ ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;ഫോട്ടോ, വീഡിയോ, സംഗീതം, ഓഡിയോ, മറ്റ് ഫയലുകൾ&lt;/b&gt; എന്നിവയിലേക്ക് &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിന് ആക്സസ് നൽകണോ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ഈ ഉപകരണത്തിലെ സംഗീതവും ഓഡിയോയും ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ സംഗീതവും ഓഡിയോയും ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ഈ ഉപകരണത്തിലെ ഫോട്ടോകളും വീഡിയോകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt; <xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ഫോട്ടോകളും വീഡിയോകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ഈ ഉപകരണത്തിലെ കൂടുതൽ ഫോട്ടോകളും വീഡിയോകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ കൂടുതൽ ഫോട്ടോകളും വീഡിയോകളും ആക്‌സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കുമ്പോൾ മാത്രമേ അതിന് ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ കഴിയൂ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും ഈ ആപ്പിന് എപ്പോഴും ഓഡിയോ റെക്കോർഡ് ചെയ്യേണ്ടതുണ്ട്. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനുള്ള മൈക്രോഫോൺ ആക്സസ് മാറ്റണോ?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനുള്ള മൈക്രോഫോൺ ആക്‌സസ് മാറ്റണോ?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും ഈ ആപ്പിന് എപ്പോഴും ഓഡിയോ റെക്കോർഡ് ചെയ്യണം. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനെ നിങ്ങളുടെ കായിക പ്രവർത്തനം ആക്‌സസ് ചെയ്യാൻ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ നിങ്ങളുടെ ശാരീരിക ആക്റ്റിവിറ്റി ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"ചിത്രം എടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ചിത്രമെടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കുമ്പോൾ മാത്രമേ അതിന് ചിത്രങ്ങളെടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാൻ കഴിയൂ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"ചിത്രം എടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ചിത്രമെടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും, ഈ ആപ്പിന് വീഡിയോ റെക്കോർഡ് ചെയ്യുക, ചിത്രമെടുക്കുക എന്നിവ ചെയ്യേണ്ടതുണ്ട്. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; എന്നതിനുള്ള ക്യാമറാ ആക്സസ് മാറ്റണോ?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനുള്ള ക്യാമറ ആക്‌സസ് മാറ്റണോ?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കാത്തപ്പോൾ പോലും, ഈ ആപ്പിന് വീഡിയോ റെക്കോർഡ് ചെയ്യുക, ചിത്രമെടുക്കുക എന്നിവ ചെയ്യണം. "<annotation id="link">"ക്രമീകരണത്തിൽ അനുവദിക്കുക."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ നിങ്ങളുടെ ഫോൺ കോൾ ചരിത്രം ആക്‌സസ് ചെയ്യാൻ &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_device_aware_phone" msgid="4389610977195521813">"നിങ്ങളുടെ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ഫോൺ കോളുകൾ ചെയ്യാനും അവ മാനേജ് ചെയ്യാനും <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ പ്രധാന ആരോഗ്യ വിവര സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ പ്രധാന ആരോഗ്യ വിവര സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"നിങ്ങൾ ആപ്പ് ഉപയോഗിക്കാത്ത സമയത്ത് ഉൾപ്പെടെ, എല്ലായ്‌പ്പോഴും ബോഡി സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ ഈ ആപ്പിനെ അനുവദിക്കുന്നതിന് "<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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ ബോഡി സെൻസർ ഡാറ്റ ആക്‌സസ് ചെയ്യാൻ &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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; എന്നതിൽ നിങ്ങൾക്ക് അറിയിപ്പുകൾ അയയ്ക്കാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"നിയന്ത്രിത അനുമതികൾ"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിന് ലൊക്കേഷൻ ആക്‌സസ് ഉണ്ട്"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"നിങ്ങളുടെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാൻ നിങ്ങളുടെ സ്ഥാപനം <xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കുന്നു"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"മൂന്നാം കക്ഷികളുമായി ലൊക്കേഷൻ ഡാറ്റ പങ്കിട്ടേക്കാമെന്ന് ഈ ആപ്പ് പ്രസ്താവിക്കുന്നു"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ഡാറ്റ പങ്കിടലും ലൊക്കേഷനും"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ഡാറ്റ പങ്കിടുന്നതിനെ കുറിച്ചുള്ള വിവരങ്ങൾ ലഭിക്കുന്നത് എവിടെ നിന്നാണ്"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ഈ ആപ്പ് എങ്ങനെയാണ് ഡാറ്റ പങ്കിടുന്നത് എന്നതിനെ കുറിച്ചുള്ള വിവരങ്ങൾ ഡെവലപ്പർ ഈ ഉപകരണത്തിന്റെ നിർമ്മാതാവിന് നൽകിയിട്ടുണ്ട്. കാലക്രമേണ ഡെവലപ്പർ ഈ വിവരങ്ങൾ അപ്ഡേറ്റ് ചെയ്തേക്കാം."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ഈ ആപ്പ് എങ്ങനെയാണ് ഡാറ്റ പങ്കിടുന്നത് എന്നതിനെ കുറിച്ച് ഡെവലപ്പർ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" എന്നതിൽ വിവരങ്ങൾ നൽകിയിട്ടുണ്ട്. കാലക്രമേണ ഡെവലപ്പർ ഈ വിവരങ്ങൾ അപ്ഡേറ്റ് ചെയ്തേക്കാം."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ഇവയ്ക്ക് ഈ ആപ്പ് ലൊക്കേഷൻ ഡാറ്റ പങ്കിട്ടേക്കാം:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ഡാറ്റ പങ്കിടുന്നത് വ്യത്യാസപ്പെടുന്നു"</string>
@@ -606,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ഡാറ്റാ സുരക്ഷ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ലൊക്കേഷൻ ഡാറ്റ പങ്കിട്ടേക്കാം"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"മൂന്നാം കക്ഷികളുമായി നിങ്ങളുടെ ലൊക്കേഷൻ ഡാറ്റ പങ്കിട്ടേക്കാമെന്ന് ഈ ആപ്പ് വ്യക്തമാക്കിയിട്ടുണ്ട്"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ഈ ലിങ്ക് തുറക്കാനാകുന്നില്ല"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ലൊക്കേഷൻ ഡാറ്റ പങ്കിടുന്നതിനുള്ള അപ്‌ഡേറ്റുകൾ"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"നിങ്ങളുടെ ലൊക്കേഷൻ ഡാറ്റ പങ്കിടുന്ന രീതി മാറ്റിയ ആപ്പുകൾ അവലോകനം ചെയ്യുക"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"നിങ്ങളുടെ ലൊക്കേഷൻ ഡാറ്റ പങ്കിടുന്ന രീതി ഈ ആപ്പുകൾ മാറ്റി. അവ ഇത് മുമ്പ് പങ്കിട്ടിട്ടുണ്ടാകില്ല, അല്ലെങ്കിൽ ഇപ്പോൾ പരസ്യം ചെയ്യൽ, മാർക്കറ്റിംഗ് എന്നിവയുമായി ബന്ധപ്പെട്ട ആവശ്യങ്ങൾക്ക് പങ്കിട്ടേക്കാം."</string>
diff --git a/PermissionController/res/values-mn-v33/strings.xml b/PermissionController/res/values-mn-v33/strings.xml
index 1da8f5e62..327723433 100644
--- a/PermissionController/res/values-mn-v33/strings.xml
+++ b/PermissionController/res/values-mn-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Бусад сэрэмжлүүлэг"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Сэрэмжлүүлгийг хаасан"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Дэлгээд дахин нэг анхааруулга харах}other{Дэлгээд дахин # анхааруулга харах}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Сэрэмжлүүлэг. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Үйлдэл дууссан"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Таны төхөөрөмжид хамгаалалт нэмэх боломжтой тохиргоог шалгана уу"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Аюулгүй байдал болон нууцлалын шуурхай тохиргоо"</string>
diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml
index c9448962e..a5ad53cf3 100644
--- a/PermissionController/res/values-mn/strings.xml
+++ b/PermissionController/res/values-mn/strings.xml
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Туслахын өдөөгч илрүүлэлтийг харуулах"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Дуут туслахыг идэвхжүүлэхийн тулд микрофоныг ашиглах үед статус самбарт дүрс тэмдэг харуулах"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д төхөөрөмжийнхөө зураг болон медиад хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны харилцагчид хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмжийн байршилд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Та тухайн аппыг ашиглаж байгаа үед энэ нь зөвхөн байршилд хандах эрхтэй болно"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмжийн байршилд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Энэ апп нь таныг апп ашиглаагүй байх үед ч таны байршилд үргэлж хандах хүcэлтэй байж болзошгүй. "<annotation id="link">"Тохиргоо хэсгээс зөвшөөрнө үү."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д зориулж байршлын хандалтыг өөрчлөх үү?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Энэ апп нь таныг апп ашиглаагүй байх үед ч таны байршилд үргэлж хандах хүcэлтэй байна. "<annotation id="link">"Тохиргоо хэсгээс зөвшөөрнө үү."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д ойр төхөөрөмжүүдийг илрүүлж, тэдгээрт холбогдож, харгалзах байршлыг нь тодорхойлохыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д ойр төхөөрөмжүүдийг илрүүлж, тэдгээрт холбогдож, харгалзах байршлыг нь тодорхойлохыг зөвшөөрөх үү? "<annotation id="link">"Тохиргоо хэсэгт зөвшөөрнө үү."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>-н байршлын хандалтыг барагцаалснаас нарийвчилсан болгож өөрчлөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмжийн барагцаалсан байршилд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Нарийвчилсан"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Барагцаалсан"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны календарьт хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д SMS мессеж илгээх болон харахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны төхөөрөмжийн зураг, медиа болон файлд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмж дээрх &lt;b&gt;зураг, видео, хөгжим болон аудионд&lt;/b&gt; хандахыг зөвшөөрөх үү?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмжийн &lt;b&gt;зураг, видео, хөгжим, аудио, бусад файлд&lt;/b&gt; хандахыг зөвшөөрөх үү?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмж дээрх хөгжим болон аудионд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмж дээрх зураг болон видеонд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д энэ төхөөрөмж дээрх бусад зураг болон видеонд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д аудио бичихийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Энэ апп зөвхөн таныг ашиглаж байх үед л аудио бичих боломжтой болно"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д аудио бичихийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Та аппыг ашиглаагүй үед ч энэ апп үргэлж аудио бичихийг хүсэж болзошгүй. "<annotation id="link">"Тохиргоонд зөвшөөрнө үү."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-н микрофоны хандалтыг өөрчлөх үү?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Та аппыг ашиглаагүй үед ч энэ апп үргэлж аудио бичихийг хүснэ. "<annotation id="link">"Тохиргоонд зөвшөөрнө үү."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны биеийн дасгал хөдөлгөөнд хандахыг зөвшөөрөх үү?"</string>
- <string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д зураг авах, видео хийхийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
+ <string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д зураг авах, видео бичихийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Энэ апп зөвхөн таныг ашиглаж байх үед л зураг авж, видео бичих боломжтой болно"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д зураг авах, видео бичихийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Та аппыг ашиглаагүй үед ч энэ апп үргэлж зураг авж, видео бичихийг хүсэж болзошгүй. "<annotation id="link">"Тохиргоонд зөвшөөрнө үү."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-н камерын хандалтыг өөрчлөх үү?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Та аппыг ашиглаагүй үед ч энэ апп үргэлж зураг авж, видео бичихийг хүснэ. "<annotation id="link">"Тохиргоонд зөвшөөрнө үү."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны утасны дуудлагын жагсаалтад хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д утасны дуудлага хийх, дуудлага удирдахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д таны биеийн ерөнхий байдлын үзүүлэлтүүдийн мэдрэгчийн өгөгдөлд хандахыг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Та аппыг ашиглаагүй байсан ч ямар ч үед энэ аппын биеийн мэдрэгчийн өгөгдөлд хандахыг зөвшөөрөх бол "<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="auto_granted_permissions" msgid="6009452264824455892">"Хяналттай зөвшөөрөл"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-&lt;/b&gt;-д танд мэдэгдэл илгээхийг зөвшөөрөх үү?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Хяналттай зөвшөөрөл"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> байршилд хандах эрхтэй байна"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Танай байгууллага <xliff:g id="APP_NAME">%1$s</xliff:g>-д байршилд тань хандахыг зөвшөөрдөг"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Бусад зөвшөөрөл"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Системийн ашигласан зөвшөөрөл"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Зөвхөн системийн аппликэйшний ашигласан зөвшөөрөл."</string>
@@ -533,7 +585,7 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"Аюулгүй байдал болон нууцлалын төлөв. <xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>. <xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"Аюулгүй байдлын тохиргоо"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Зөвшөөрөл"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Аюулгүй байдал &amp; нууцлал"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Аюулгүй байдал ба нууцлал"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Төлөвийг шалгах"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Таны нууцлалын тохиргоо"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Бусад тохиргоо"</string>
@@ -587,10 +639,11 @@
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Түр санах ойн хандалтыг харуулах"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Аппууд таны хуулсан текст, зураг эсвэл бусад контентод хандах үед мессеж харуулах"</string>
<string name="show_password_title" msgid="2877269286984684659">"Нууц үгнүүдийг харуулах"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Таныг бичиж явцад тэмдэгтүүдийг түр үзүүлэх"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Бичих явцад тэмдэгтийг товчхон харуулах"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Энэ апп байршлын өгөгдлийг гуравдагч талуудтай хуваалцаж болохыг мэдэгдсэн"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Өгөгдөл хуваалцах болон байршил"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Өгөгдөл хуваалцах мэдээллийг хаанаас авдаг вэ?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Хөгжүүлэгч энэ төхөөрөмжийн үйлдвэрлэгчид уг апп хэрхэн өгөгдөл хуваалцдаг талаарх мэдээллийг өгсөн. Хөгжүүлэгч энэ мэдээллийг яваандаа шинэчилж магадгүй."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Хөгжүүлэгч энэ апп өгөгдөл хэрхэн хуваалцдаг талаарх мэдээллийг "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s-д"</annotation></annotation>" өгсөн. Хөгжүүлэгч энэ мэдээллийг цагийн аясаар шинэчилж магадгүй."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Апп байршлын өгөгдөл дараах зорилгоор хуваалцана:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Өгөгдөл хуваалцах нь ялгаатай"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Өгөгдлийн аюулгүй байдал"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Байршлын өгөгдлийг хуваалцаж магадгүй"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Энэ апп таны байршлын өгөгдлийг гуравдагч талуудтай хуваалцаж магадгүйг мэдэгдсэн"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Энэ холбоосыг нээх боломжгүй"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Байршлын өгөгдөл хуваалцах шинэчлэлтүүд"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Таны байршлын өгөгдлийг хуваалцдаг аргаа өөрчилсөн аппуудыг шалгана уу"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Эдгээр апп таны байршлын өгөгдлийг хуваалцдаг аргаа өөрчилсөн. Тэд үүнийг өмнө нь хуваалцаагүй байж магадгүй эсвэл одоо үүнийг сурталчилгаа, маркетингийн зорилгоор хуваалцаж болзошгүй."</string>
diff --git a/PermissionController/res/values-mr-v33/strings.xml b/PermissionController/res/values-mr-v33/strings.xml
index f9de83102..cea91a4b2 100644
--- a/PermissionController/res/values-mr-v33/strings.xml
+++ b/PermissionController/res/values-mr-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"आणखी सूचना"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"डिसमिस केलेल्या सूचना"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{विस्तार करा आणि आणखी एक सूचना पहा}other{विस्तार करा आणि आणखी # सूचना पहा}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"इशारा. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"कृती पूर्ण झाली आहे"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"तुमच्या डिव्हाइसला संरक्षण जोडू शकतील अशी सेटिंग्ज तपासा"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"सुरक्षा आणि गोपनीयता क्विक सेटिंग्ज"</string>
diff --git a/PermissionController/res/values-mr-v34/strings.xml b/PermissionController/res/values-mr-v34/strings.xml
index 1785fd7f2..8c9152379 100644
--- a/PermissionController/res/values-mr-v34/strings.xml
+++ b/PermissionController/res/values-mr-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"सुरक्षा आणि गोपनीयता"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"नियंत्रणे"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"आरोग्यविषयक डेटासंबंधित अ‍ॅपचा अ‍ॅक्सेस नियंत्रित करा"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"आरोग्यविषयक डेटासंबंधित अ‍ॅपचा अ‍ॅक्सेस व्यवस्थापित करा"</string>
<string name="location_settings" msgid="8863940440881290182">"स्थान अ‍ॅक्सेस"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ॲप्स आणि सेवांसाठी. हे सेटिंग बंद असल्यास, तुम्ही आणीबाणी नंबरवर कॉल करता, तेव्हा मायक्रोफोन डेटा तरीही शेअर केला जाऊ शकतो"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ॲप्स आणि सेवांसाठी"</string>
diff --git a/PermissionController/res/values-mr/strings.xml b/PermissionController/res/values-mr/strings.xml
index 1dfffc9d3..5335f6ca6 100644
--- a/PermissionController/res/values-mr/strings.xml
+++ b/PermissionController/res/values-mr/strings.xml
@@ -20,7 +20,7 @@
<string name="ok" msgid="1936281769725676272">"ओके"</string>
<string name="permission_search_keyword" msgid="1214451577494730543">"परवानग्या"</string>
<string name="cancel" msgid="8943320028373963831">"रद्द करा"</string>
- <string name="back" msgid="6249950659061523680">"परत"</string>
+ <string name="back" msgid="6249950659061523680">"मागे जा"</string>
<string name="available" msgid="6007778121920339498">"उपलब्ध आहे"</string>
<string name="blocked" msgid="9195547604866033708">"ब्लॉक केला आहे"</string>
<string name="on" msgid="280241003226755921">"सुरू आहे"</string>
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"अचूक स्थान वापरा"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"अचूक स्थान बंद असते, तेव्हा ॲप्स तुमचे अंदाजे स्थान अ‍ॅक्सेस करू शकतात"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> परवानगी"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"या अ‍ॅपसाठी <xliff:g id="PERM">%1$s</xliff:g> चा अ‍ॅक्सेस द्या"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"या अ‍ॅपसाठी <xliff:g id="PERM">%1$s</xliff:g> अ‍ॅक्सेस द्या"</string>
<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>
@@ -397,8 +397,8 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि तुमचा फोन, एसएमएस, संपर्क आणि Calendar च्या परवानग्या अ‍ॅक्सेस करण्याची अनुमती मिळेल."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमच्या सूचनांशी संवाद साधण्याची आणि कनेक्‍ट केलेल्या डिव्हाइसवर तुमची ॲप्स स्ट्रीम करण्याची अनुमती दिली जाईल."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"ही सेवा तुमचे फोटो, मीडिया आणि सूचना तुमच्या फोनवरून दुसऱ्या डिव्हाइसवर शेअर करते."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"डीफॉल्ट टीपांचे अ‍ॅप"</string>
- <string name="role_notes_short_label" msgid="8796604147546125285">"टीपांचे अ‍ॅप"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"टिपांसाठी डीफॉल्ट अ‍ॅप"</string>
+ <string name="role_notes_short_label" msgid="8796604147546125285">"टिपांचे अ‍ॅप"</string>
<string name="role_notes_description" msgid="8496852798616883551">"तुमच्या डिव्हाइसवर तुम्हाला टिपा घेण्याची अनुमती देणारी अ‍ॅप्स"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"टिपा"</string>
<string name="request_role_current_default" msgid="738722892438247184">"सद्य डीफॉल्ट"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"असिस्टंट ट्रिगर डिटेक्शन दाखवा"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"व्हॉइस असिस्टंट अ‍ॅक्टिव्हेट करण्यासाठी मायक्रोफोन वापरला जाईल तेव्हा स्टेटस बारमध्ये आयकन दाखवा"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या डिव्हाइसवरील फोटो आणि मीडिया अ‍ॅक्सेस करू द्यायचा?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे संपर्क अ‍ॅक्सेस करू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसचे स्थान ॲक्सेस करू द्यायचे आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"तुम्ही अ‍ॅप वापरत असताना अ‍ॅपला फक्त स्थानाचा अ‍ॅक्सेस असेल"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसचे स्थान ॲक्सेस करू द्यायचे आहे का?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"तुम्ही अ‍ॅप वापरत नसतानादेखील कदाचित या ॲपला नेहमी तुमचे स्थान ॲक्सेस करायचे आहे."<annotation id="link">"सेटिंग्जमधून अनुमती द्या."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; चा स्थान ॲक्सेस बदलायचा आहे का?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"तुम्ही अ‍ॅप वापरत नसतानादेखील या ॲपला नेहमी तुमचे स्थान ॲक्सेस करायचे आहे. "<annotation id="link">"सेटिंग्जमधून अनुमती द्या."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला जवळील डिव्हाइस शोधण्याची, त्यांच्याशी कनेक्ट व त्यांचे संबंधित स्थान निर्धारित करण्याची अनुमती द्यायची का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला जवळील डिव्हाइस शोधण्याची, त्यांच्याशी कनेक्ट व त्यांचे संबंधित स्थान निर्धारित करण्याची अनुमती द्यायची का? "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> च्या स्थानाचा अ‍ॅक्सेस अंदाजेवरून अचूकवर बदलायचा आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसचे अंदाजे स्थान ॲक्सेस करू द्यायचे आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"अचूक"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"अंदाजे"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे कॅलेंडर अ‍ॅक्सेस करू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला एसएमएस पाठवू आणि पाहू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या डिव्हाइसवरील फोटो, मीडिया आणि फाइल अ‍ॅक्सेस करू द्यायच्या?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसवरील &lt;b&gt;फोटो, व्हिडिओ, संगीत आणि ऑडिओ&lt;/b&gt; अ‍ॅक्सेस करू द्यायचा आहे का?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसवरील &lt;b&gt;फोटो, व्हिडिओ, संगीत, ऑडिओ व इतर फाइल&lt;/b&gt; अ‍ॅक्सेस करू द्यायच्या?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसवरील संगीत आणि ऑडिओ अ‍ॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसवरील फोटो आणि व्हिडिओ अ‍ॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला या डिव्हाइसवरील अधिक फोटो आणि व्हिडिओ अ‍ॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला ऑडिओ रेकॉर्ड करू द्यायचा?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ॲप फक्त तुम्ही ॲप वापरत असतानाच ऑडिओ रेकॉर्ड करू शकते"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला ऑडिओ रेकॉर्ड करायची अनुमती द्यायची?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"हे ॲप तुम्ही ॲप वापरत नसतानादेखील ऑडिओ नेहमी रेकॉर्ड करू शकते. "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; चा मायक्रोफोनचा ॲक्सेस बदलायचा?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"हे ॲप तुम्ही ॲप वापरत नसतानादेखील नेहमी ऑडिओ रेकॉर्ड करू शकते. "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमची शारीरिक अ‍ॅक्टिव्हिटी अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला फोटो काढू आणि व्हिडिओ रेकॉर्ड करू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ॲप फक्त तुम्ही ॲप वापरत असतानाच फोटो काढू शकते आणि व्हिडिओ रेकॉर्ड करू शकते"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला फोटो काढायची आणि व्हिडिओ रेकॉर्ड करायची अनुमती द्यायची?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"हे ॲप तुम्ही ॲप वापरत नसतानादेखील नेहमी फोटो काढू शकते आणि व्हिडिओ रेकॉर्ड करू शकते."<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; चा कॅमेऱ्याचा अ‍ॅक्सेस बदलायचा?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"हे ॲप तुम्ही ॲप वापरत नसतानादेखील नेहमी फोटो काढू शकते आणि व्हिडिओ रेकॉर्ड करू शकते. "<annotation id="link">"सेटिंग्जमध्ये अनुमती द्या."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमचे फोन कॉल लॉग अ‍ॅक्सेस करण्याची अनुमती द्यायची का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला फोन कॉल करू आणि ते व्यवस्थापित करू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमच्या महत्त्वाच्या लक्षणांविषयीचा सेन्सर डेटा अ‍ॅक्सेस करू द्यायचे?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"तुम्ही ॲप वापरत नसतानादेखील या ॲपला शरीर सेन्सर डेटा नेहमी अ‍ॅक्सेस करू देण्यासाठी, "<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="auto_granted_permissions" msgid="6009452264824455892">"नियंत्रित परवानग्या"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुम्हाला सूचना पाठवू द्यायचे का?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"नियंत्रित परवानग्या"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> कडे स्थान अ‍ॅक्सेस आहे"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"तुमची संस्था <xliff:g id="APP_NAME">%1$s</xliff:g> ला तुमचे स्थान अ‍ॅक्सेस करण्याची अनुमती देते"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"इतर परवानग्या"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"सिस्टमद्वारे वापरल्या जाणाऱ्या परवानग्या"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"फक्त सिस्टम ॲप्लिकेशनद्वारे वापरल्या जाणाऱ्या परवानग्या."</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"ॲप्स आणि सेवांसाठी. हे सेटिंग बंद असल्यास, तुम्ही आणीबाणी नंबरवर कॉल करता तेव्हा, मायक्रोफोन डेटा तरीही कदाचित शेअर केला जाईल."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"स्थानाचा अ‍ॅक्सेस असलेली अ‍ॅप्स आणि सेवा पहा"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"क्लिपबोर्डचा अ‍ॅक्सेस दाखवा"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"तुम्ही कॉपी केलेला मजकूर, इमेज किंवा इतर आशय ॲप्स अ‍ॅक्सेस करतात तेव्हा, मेसेज दाखवा"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"तुम्ही कॉपी केलेला मजकूर, इमेज किंवा इतर आशय ॲप्स अ‍ॅक्सेस करतात, तेव्हा मेसेज दाखवा"</string>
<string name="show_password_title" msgid="2877269286984684659">"पासवर्ड दाखवा"</string>
<string name="show_password_summary" msgid="1110166488865981610">"तुम्ही टाइप कराल त्‍याप्रमाणे वर्ण थोडक्‍यात डिस्प्ले करा"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"हे अ‍ॅप तृतीय पक्षांसोबत स्थान डेटा शेअर करू शकते असे या अ‍ॅपने नमूद केले आहे"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"डेटा शेअरिंग आणि स्थान"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"डेटा शेअरिंग माहिती कुठून मिळते"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"हे ॲप डेटा कसे शेअर करते याबद्दल डेव्हलपरने या डिव्हाइसच्या उत्पादकाला माहिती पुरवली आहे. डेव्हलपर कालांतराने ही माहिती अपडेट करू शकतो."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"हे अ‍ॅप डेटा कसे शेअर करते याबद्दल डेव्हलपरने "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" यांना माहिती पुरवली. डेव्हलपर कालांतराने ही माहिती अपडेट करू शकतो."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"अ‍ॅप पुढील गोष्टींसाठी स्‍थान डेटा शेअर करू शकते:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"डेटा शेअरिंग बदलते"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"डेटासंबंधित सुरक्षितता"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"स्‍थान डेटा शेअर केला जाऊ शकतो"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"हे अ‍ॅप तृतीय पक्षांसोबत तुमचा स्थान डेटा शेअर करू शकते असे या अ‍ॅपने नमूद केले आहे"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ही लिंक उघडू शकत नाही"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"स्थानासाठी डेटा शेअरिंगसंबंधित अपडेट"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ज्या अ‍ॅप्सनी तुमचा स्थान डेटा शेअर करण्याची त्यांची पद्धत बदलली अशा अ‍ॅप्सचे पुनरावलोकन करा"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"या अ‍ॅप्सनी तुमचा स्थान डेटा शेअर करण्याची त्यांची पद्धत बदलली आहे. त्यांनी तो पूर्वी शेअर केलेला नसू शकतो किंवा आता जाहिरात करणे अथवा मार्केटिंग उद्देशांसाठी शेअर करू शकतात."</string>
diff --git a/PermissionController/res/values-ms-v33/strings.xml b/PermissionController/res/values-ms-v33/strings.xml
index 95643d003..d5540a429 100644
--- a/PermissionController/res/values-ms-v33/strings.xml
+++ b/PermissionController/res/values-ms-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Lagi makluman"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Makluman yang diketepikan"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Kembangkan dan lihat satu makluman lagi}other{Kembangkan dan lihat # makluman lagi}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Amaran. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Tindakan selesai"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Semak tetapan yang boleh menambah perlindungan pada peranti anda"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Tetapan pantas keselamatan dan privasi"</string>
diff --git a/PermissionController/res/values-ms/strings.xml b/PermissionController/res/values-ms/strings.xml
index f08513a18..bd7d99682 100644
--- a/PermissionController/res/values-ms/strings.xml
+++ b/PermissionController/res/values-ms/strings.xml
@@ -455,53 +455,78 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Tunjukkan pengesanan cetusan pembantu"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Tunjukkan ikon dalam bar status apabila mikrofon digunakan untuk mengaktifkan pembantu suara"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan media pada peranti anda?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan media pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kenalan anda?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kenalan anda pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi peranti ini?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>s&lt;/b&gt; anda?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Apl ini hanya dapat mengakses lokasi semasa anda menggunakan apl tersebut"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi peranti ini?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g> anda?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Apl ini mungkin mahu mengakses lokasi anda pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Tukar akses lokasi untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Tukar akses lokasi untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Apl ini mahu mengakses lokasi anda pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk mencari, menyambung kepada dan menentukan penempatan relatif peranti berdekatan?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mencari, menyambung &amp; menentukan kedudukan relatif peranti berdekatan pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; untuk mencari, menyambung kepada dan menentukan penempatan relatif peranti berdekatan? "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Tukar akses lokasi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> daripada anggaran kepada tepat?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Tukar akses lokasi <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda daripada lokasi anggaran kepada lokasi tepat?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi anggaran peranti ini?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lokasi anggaran &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Tepat"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Anggaran"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kalendar anda?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses kalendar anda pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menghantar dan melihat mesej SMS?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menghantar dan melihat mesej SMS pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto, media dan fail pada peranti anda?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto, media dan fail pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses &lt;b&gt;foto, video, muzik dan audio&lt;/b&gt; pada peranti ini?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses &lt;b&gt;foto, video, muzik, audio dan fail lain&lt;/b&gt; pada peranti ini?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses muzik dan audio pada peranti ini?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses muzik dan audio pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan video pada peranti ini?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses foto dan video pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lebih banyak foto dan video pada peranti ini?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses lebih banyak foto dan video pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merakam audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merakam audio pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Apl hanya boleh merakam audio semasa anda menggunakan apl tersebut"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merakam audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merakam audio pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Apl ini mungkin mahu merakam audio pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Tukar akses mikrofon untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Tukar akses mikrofon untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Apl ini mahu merakam audio pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses aktiviti fizikal anda?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses aktiviti fizikal anda pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merakam video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merakam video pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Apl hanya boleh mengambil gambar dan merakam video semasa anda menggunakan apl tersebut"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merakam video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merakam video pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Apl ini mungkin mahu mengambil gambar dan merakam video pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Tukar akses kamera untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Tukar akses kamera untuk &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Apl ini mahu mengambil gambar dan merakam video pada sepanjang masa, meskipun apabila anda tidak menggunakan apl itu. "<annotation id="link">"Benarkan dalam tetapan."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses log panggilan telefon anda pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; 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_device_aware_phone" msgid="4389610977195521813">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; membuat dan mengurus panggilan telefon pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tentang tanda vital pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tentang tanda vital pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Untuk membenarkan apl ini mengakses data penderia tubuh pada setiap masa, termasuk 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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Terus membenarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengakses data penderia tubuh pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda 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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; menghantar pemberitahuan kepada anda pada &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; anda?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kebenaran terkawal"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
- <skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
- <skip />
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> memiliki akses lokasi"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organisasi anda membenarkan <xliff:g id="APP_NAME">%1$s</xliff:g> untuk mengakses lokasi anda"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Kebenaran lain"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Kebenaran digunakan oleh sistem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Kebenaran digunakan hanya oleh aplikasi sistem"</string>
@@ -591,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Apl ini menyatakan bahawa data lokasi mungkin dikongsi dengan pihak ketiga"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Perkongsian data dan lokasi"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Sumber maklumat perkongsian data"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Pembangun menyediakan maklumat kepada pengilang peranti ini tentang cara apl ini berkongsi data. Pembangun boleh mengemaskinikan maklumat ini dari semasa ke semasa."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Pembangun menyediakan maklumat kepada "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" tentang cara apl ini berkongsi data. Pembangun mungkin mengemaskinikan maklumat ini dari semasa ke semasa."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Apl ini mungkin berkongsi data lokasi untuk:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Perkongsian data berbeza-beza"</string>
@@ -608,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Keselamatan data"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Data lokasi mungkin dikongsi"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Apl ini menyatakan bahawa data lokasi anda mungkin dikongsi dengan pihak ketiga"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Tidak dapat membuka pautan ini"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Kemaskinian perkongsian data untuk lokasi"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Semak apl yang mengubah cara apl itu boleh berkongsi data lokasi anda"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Apl ini telah mengubah cara apl boleh berkongsi data lokasi anda. Apl mungkin tidak berkongsi data lokasi sebelum ini atau mungkin berkongsi data lokasi sekarang untuk tujuan pengiklanan atau pemasaran."</string>
diff --git a/PermissionController/res/values-my-v33/strings.xml b/PermissionController/res/values-my-v33/strings.xml
index cb3ca6f69..33237070b 100644
--- a/PermissionController/res/values-my-v33/strings.xml
+++ b/PermissionController/res/values-my-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"နောက်ထပ် သတိပေးချက်များ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ပယ်ထားသော သတိပေးချက်များ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ချဲ့ပြီး သတိပေးချက်နောက်တစ်ခု ကြည့်ရန်}other{ချဲ့ပြီး သတိပေးချက်နောက် # ခု ကြည့်ရန်}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"သတိပေးချက်။ <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"လုပ်ဆောင်ချက် ပြီးပြီ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"သင့်စက်တွင် အကာအကွယ်ထည့်သွင်းနိုင်သည့် ဆက်တင်များကို ကြည့်နိုင်သည်"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"လုံခြုံရေးနှင့် ကိုယ်ရေးဒေတာ အမြန်ဆက်တင်များ"</string>
diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml
index a7f85acf2..1040422f8 100644
--- a/PermissionController/res/values-my/strings.xml
+++ b/PermissionController/res/values-my/strings.xml
@@ -23,7 +23,7 @@
<string name="back" msgid="6249950659061523680">"နောက်သို့"</string>
<string name="available" msgid="6007778121920339498">"ရနိုင်သည်"</string>
<string name="blocked" msgid="9195547604866033708">"ပိတ်ထားသည်"</string>
- <string name="on" msgid="280241003226755921">"ဖွင့်ထားသည်"</string>
+ <string name="on" msgid="280241003226755921">"ဖွင့်"</string>
<string name="off" msgid="1438489226422866263">"ပိတ်"</string>
<string name="uninstall_or_disable" msgid="4496612999740858933">"ပရိုဂရမ်ကို ဖယ်ရှားရန် သို့မဟုတ် ပိတ်ရန်"</string>
<string name="app_not_found_dlg_title" msgid="6029482906093859756">"အက်ပ် မတွေ့ပါ"</string>
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"မည်သို့ပင်ဖြစ်စေ ခွင့်မပြုပါ"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"ပယ်ရန်"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> ထဲမှ <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g> ရန်ခွင့်ပြုမလား။"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g> ရန် အမြဲခွင့်ပြုသလား။"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g>ခွင့် ပြုမလား။"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို <xliff:g id="ACTION">%2$s</xliff:g>ခွင့် အမြဲပြုသလား။"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"အက်ပ်အသုံးပြုစဉ်သာ"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"အမြဲတမ်း"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"ခွင့်မပြုပါ၊ ထပ်မမေးပါနှင့်"</string>
@@ -397,7 +397,7 @@
<string name="role_watch_description" msgid="267003778693177779">"သင်၏ ‘ဖုန်း’၊ ‘SMS စာတိုစနစ်’၊ ‘အဆက်အသွယ်များ’ နှင့် ‘ပြက္ခဒိန်’ ခွင့်ပြုချက်များကို သုံးရန်နှင့် အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ခွင့်ပြုပါမည်။"</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"သင့်အကြောင်းကြားချက်များကို ပြန်လှန်တုံ့ပြန်ရန်နှင့် သင့်အက်ပ်များကို ချိတ်ဆက်ထားသောစက်သို့ တိုက်ရိုက်လွှင့်ရန် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို ခွင့်ပြုပါမည်။"</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"ဤဝန်ဆောင်မှုသည် သင်၏ဖုန်းမှ ဓာတ်ပုံ၊ မီဒီယာနှင့် အကြောင်းကြားချက်များကို အခြားစက်ပစ္စည်းများသို့ မျှဝေသည်။"</string>
- <string name="role_notes_label" msgid="7451627001058089536">"မူလ မှတ်စုရေးသောအက်ပ်"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"မူရင်း မှတ်စုအက်ပ်"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"မှတ်စုရေးသောအက်ပ်"</string>
<string name="role_notes_description" msgid="8496852798616883551">"စက်ပစ္စည်းတွင် မှတ်စုရေးခွင့်ပြုသော အက်ပ်များ"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"မှတ်စုများ"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"အကူအညီစတင်ရန် သိရှိမှုစနစ်ကို ပြပါ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"အသံအကူအညီ စတင်ရန် မိုက်ခရိုဖုန်းအသုံးပြုသည့်အခါ သင်္ကေတကို အခြေအနေဘားတွင် ပြပါ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင့်စက်ပေါ်ရှိ ဓာတ်ပုံနှင့် မီဒီယာဖိုင်များ ဝင်သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏အဆက်အသွယ်များကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ဤစက်ပစ္စည်း၏တည်နေရာကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"အက်ပ်ကိုအသုံးပြုသည့် အချိန်တွင်သာ ၎င်းကတည်နေရာကို အသုံးပြုခွင့်ရပါမည်"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ဤစက်ပစ္စည်း၏တည်နေရာကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"သင် အသုံးမပြုနေလျှင်တောင်မှ ဤအက်ပ်က သင့်တည်နေရာကို သုံးခွင့်ရနေပါမည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt တို့အတွက် တည်နေရာ ဝင်ခွင့် ပြောင်းပေးမလား။"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"သင် အသုံးမပြုနေလျှင်တောင်မှ ဤအက်ပ်က သင့်တည်နေရာကို သုံးခွင့်ရလိုသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"အနီးရှိ စက်များ၏ မှန်းခြေနေရာ ရှာရန်၊ ချိတ်ဆက်ရန်နှင့် သတ်မှတ်ရန် &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို ခွင့်ပြုမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"အနီးရှိ စက်များ၏မှန်းခြေနေရာကို ရှာရန်၊ ချိတ်ဆက်ရန်နှင့် သတ်မှတ်ရန် &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ခွင့်ပြုမလား။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ၏ တည်နေရာသုံးခွင့်ကို ခန့်မှန်းခြေမှ အတိအကျသို့ ပြောင်းမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ဤစက်၏ တည်နေရာခန့်မှန်းခြေကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"နေရာအတိအကျ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ခန့်မှန်းခြေ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ပြက္ခဒိန်ကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား SMS မက်ဆေ့ဂျ်များ ကြည့်ရှုခွင့်နှင့် ပို့ခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင့်ဖုန်းရှိ ဓာတ်ပုံများ၊ မီဒီယာနှင့် ဖိုင်များ ဝင်သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ဤစက်ရှိ &lt;b&gt;ဓာတ်ပုံ၊ ဗီဒီယို၊ တေးဂီတနှင့် အသံများ&lt;/b&gt; ကို &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သုံးခွင့်ပေးမလား။"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"စက်ရှိ &lt;b&gt;ဓာတ်ပုံ၊ ဗီဒီယို၊ တေးဂီတ၊ အသံနှင့်အခြားဖိုင်များ&lt;/b&gt; ကို &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သုံးခွင့်ပေးမလား။"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ဤစက်ရှိ တေးဂီတနှင့် အသံဖိုင်ကို &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သုံးခွင့်ပေးမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ဤစက်ရှိ ဓာတ်ပုံနှင့် ဗီဒီယိုများကို &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သုံးခွင့်ပေးမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ဤစက်ရှိ နောက်ထပ်ဓာတ်ပုံနှင့် ဗီဒီယိုများကို &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သုံးခွင့်ပေးမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို အသံဖမ်းယူခွင့် ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ဤအက်ပ်ကို အသုံးပြုနေသည့် အချိန်တွင်သာ ၎င်းက အသံဖမ်းနိုင်သည်။"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို အသံဖမ်းခွင့် ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ဤအက်ပ်ကို သင်အသုံးမပြုနေလျှင်ပင် ၎င်းက တစ်ချိန်လုံး အသံဖမ်းယူလိုသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt အတွက် မိုက်ခရိုဖုန်း အသုံးပြုခွင့် ပြောင်းမလား။"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ဤအက်ပ်ကို သင်အသုံးမပြုနေလျှင်ပင် ၎င်းက တစ်ချိန်လုံး အသံဖမ်းလိုသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင့်ကိုယ်ခန္ဓာလှုပ်ရှားမှုကို ဝင်ကြည့်ခွင့် ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ဓာတ်ပုံနှင့် ဗီဒီယိုရိုက်ကူးခွင့် ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ဤအက်ပ်ကို အသုံးပြုနေသည့် အချိန်တွင်သာ ၎င်းက ဓာတ်ပုံနှင့် ဗီဒီယိုများကို ရိုက်ကူးနိုင်သည်။"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို ဓာတ်ပုံနှင့် ဗီဒီယိုရိုက်ကူးခွင့် ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ဤအက်ပ်ကို သင်အသုံးမပြုနေလျှင်ပင် ၎င်းက ဓာတ်ပုံနှင့် ဗီဒီယိုများကို တစ်ချိန်လုံး ရိုက်ကူးလိုသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt အတွက် ကင်မရာအသုံးပြုခွင့် ပြောင်းမလား။"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ဤအက်ပ်ကို သင်အသုံးမပြုနေလျှင်ပင် ၎င်းက ဓာတ်ပုံနှင့် ဗီဒီယိုများကို တစ်ချိန်လုံး ရိုက်ကူးလိုသည်။ "<annotation id="link">"ဆက်တင်များတွင် ခွင့်ပြုပါ။"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ခေါ်ဆိုထားသော မှတ်တမ်းများကို သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို ဖုန်းခေါ်ဆိုမှုများ ပြုလုပ်ခွင့်နှင့် စီမံခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ အရေးကြီးသော ကျန်းမာရေးလက္ခဏာဆိုင်ရာ အာရုံခံကိရိယာဒေတာ သုံးခွင့်ပေးလိုပါသလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"အက်ပ်သုံးမနေသော်လည်း ဤအက်ပ်ကို ခန္ဓာကိုယ်အာရုံခံစနစ် ဒေတာများ အမြဲသုံးခွင့်ပြုရန် "<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="auto_granted_permissions" msgid="6009452264824455892">"ထိန်းချုပ်ထားသော ခွင့်ပြုချက်များ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ကို သင့်ထံ အကြောင်းကြားချက်များ ပို့ခွင့်ပြုမလား။"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"ထိန်းချုပ်ထားသော ခွင့်ပြုချက်များ"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> တွင် တည်နေရာသုံးခွင့်ရှိသည်"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"သင်၏အဖွဲ့အစည်းက <xliff:g id="APP_NAME">%1$s</xliff:g> အား သင့်တည်နေရာကို သုံးခွင့်ပြုသည်"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"အခြားခွင့်ပြုချက်များ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"စနစ်က အသုံးပြုသည့် ခွင့်ပြုချက်"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"စနစ် အပလီကေးရှင်းများကသာ အသုံးပြုသည့် ခွင့်ပြုချက်များ။"</string>
@@ -584,13 +636,14 @@
<string name="perm_toggle_description" msgid="7801326363741451379">"အက်ပ်နှင့် ဝန်ဆောင်မှုများအတွက်"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"အက်ပ်နှင့် ဝန်ဆောင်မှုများအတွက်။ ဤဆက်တင်ကို ပိတ်ထားသော်လည်း အရေးပေါ် နံပါတ်ကို သင်ခေါ်ဆိုချိန်တွင် မိုက်ခရိုဖုန်းဒေတာကို မျှဝေနိုင်သေးသည်။"</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"တည်နေရာသုံးခွင့်ရှိသော အက်ပ်နှင့် ဝန်ဆောင်မှုများကို ကြည့်ပါ"</string>
- <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ကလစ်ဘုတ်အသုံးပြုမှုကို ပြခြင်း"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"အက်ပ်များက သင်မိတ္တူကူးထားသော စာသား၊ ပုံများ (သို့) အခြားအကြောင်းအရာကို သုံးသောအခါ အကြောင်းကြားပါ"</string>
+ <string name="show_clip_access_notification_title" msgid="5168467637351109096">"ကလစ်ဘုတ်အသုံးပြုမှု ပြရန်"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"အက်ပ်များက သင်မိတ္တူကူးထားသော စာသား၊ ပုံများ (သို့) အခြားအကြောင်းအရာကို သုံးသောအခါ အကြောင်းကြားသည်"</string>
<string name="show_password_title" msgid="2877269286984684659">"စကားဝှက်များပြရန်"</string>
<string name="show_password_summary" msgid="1110166488865981610">"စာရိုက်သည့်အခါ အက္ခရာများကို ခဏတာပြသည်"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ဤအက်ပ်က ၎င်းသည် ဒေတာကို ပြင်ပအဖွဲ့များနှင့် မျှဝေနိုင်ကြောင်း ဖော်ပြထားသည်"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ဒေတာမျှဝေခြင်းနှင့် တည်နေရာ"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ဒေတာမျှဝေခြင်း အချက်အလက် ရလာသောနေရာ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ဆော့ဖ်ဝဲရေးသူသည် ဤအက်ပ် ဒေတာမျှဝေပုံအကြောင်း အချက်အလက်ကို ဤစက်၏ ထုတ်လုပ်သူထံသို့ ပေးထားသည်။ ဆော့ဖ်ဝဲရေးသူက ဤအချက်အလက်ကို အချိန်နှင့်အမျှ အပ်ဒိတ်လုပ်နိုင်သည်။"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ဆော့ဖ်ဝဲရေးသူသည် ဤအက်ပ် ဒေတာမျှဝေပုံအကြောင်း အချက်အလက်ကို "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" သို့ ပေးထားသည်။ ဆော့ဖ်ဝဲရေးသူက ဤအချက်အလက်ကို အချိန်နှင့်အမျှ အပ်ဒိတ်လုပ်နိုင်သည်။"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ဤအက်ပ်က အောက်ပါတို့ကြောင့် တည်နေရာဒေတာမျှဝေနိုင်သည်-"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ဒေတာမျှဝေခြင်း ကွဲပြားပုံ"</string>
@@ -608,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ဒေတာ ဘေးကင်းလုံခြုံရေး"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"တည်နေရာဒေတာကို မျှဝေနိုင်သည်"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ဤအက်ပ်က ၎င်းသည် သင်၏ တည်နေရာဒေတာကို ပြင်ပကုမ္ပဏီများနှင့် မျှဝေနိုင်ကြောင်း ဖော်ပြထားသည်"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ဤလင့်ခ်ကို ဖွင့်၍မရပါ"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"တည်နေရာအတွက် ဒေတာမျှဝေခြင်း အပ်ဒိတ်"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"သင်၏ တည်နေရာဒေတာ မျှဝေနိုင်သောနည်းလမ်းအား ပြောင်းထားသော အက်ပ်များကို စိစစ်ပါ"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"သင်၏ တည်နေရာဒေတာ မျှဝေနိုင်သောနည်းလမ်းအား ပြောင်းထားသော အက်ပ်များကို စိစစ်သည်"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ဤအက်ပ်များသည် ၎င်းတို့က သင်၏ တည်နေရာဒေတာ မျှဝေနိုင်သော နည်းလမ်းကို ပြောင်းလိုက်ပါပြီ။ ၎င်းတို့သည် ဒေတာကို ယခင်က မျှဝေထားခြင်း မရှိနိုင်ပါ သို့မဟုတ် ကြော်ငြာခြင်း (သို့) အရောင်းမြှင့်တင်ခြင်းတို့အတွက် ဒေတာကို ယခုမျှဝေနိုင်သည်။"</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"ဤအက်ပ်များ၏ ဆော့ဖ်ဝဲရေးသူများသည် ၎င်းတို့၏ ဒေတာမျှဝေခြင်း လုပ်ထုံးလုပ်နည်းများအကြောင်း အချက်အလက်ကို အက်ပ်စတိုးသို့ ပေးထားသည်။ သူတို့သည် ၎င်းကို အချိန်နှင့်အမျှ အပ်ဒိတ်လုပ်နိုင်သည်။\n\nဒေတာမျှဝေခြင်း လုပ်ထုံးလုပ်နည်းများသည် သင်၏ အက်ပ်ဗားရှင်း၊ အသုံးပြုမှု၊ ဒေသနှင့် အသက်အရွယ်ပေါ် အခြေခံ၍ ကွဲပြားနိုင်သည်။"</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"ဒေတာမျှဝေခြင်းအကြောင်း လေ့လာရန်"</string>
diff --git a/PermissionController/res/values-nb-v33/strings.xml b/PermissionController/res/values-nb-v33/strings.xml
index 88d17ffcc..570e99d27 100644
--- a/PermissionController/res/values-nb-v33/strings.xml
+++ b/PermissionController/res/values-nb-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Flere varsler"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Avviste varsler"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Dobbelttrykk for å se et varsel til}other{Dobbelttrykk for å se # varsler til}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Varsel. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Handlingen er fullført"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Sjekk innstillinger som kan øke beskyttelsen til enheten"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Hurtiginnstillinger for sikkerhet og personvern"</string>
diff --git a/PermissionController/res/values-nb/strings.xml b/PermissionController/res/values-nb/strings.xml
index 26ccb9950..f9b35c244 100644
--- a/PermissionController/res/values-nb/strings.xml
+++ b/PermissionController/res/values-nb/strings.xml
@@ -48,7 +48,7 @@
<string name="permission_revoked_count" msgid="4785082705441547086">"<xliff:g id="COUNT">%1$d</xliff:g> er slått av"</string>
<string name="permission_revoked_all" msgid="3397649017727222283">"alt er slått av"</string>
<string name="permission_revoked_none" msgid="9213345075484381180">"ingen er slått av"</string>
- <string name="grant_dialog_button_allow" msgid="5314677880021102550">"Ja"</string>
+ <string name="grant_dialog_button_allow" msgid="5314677880021102550">"Tillat"</string>
<string name="grant_dialog_button_allow_always" msgid="4485552579273565981">"Tillat hele tiden"</string>
<string name="grant_dialog_button_allow_foreground" msgid="501896824973636533">"Når appen brukes"</string>
<string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"Bytt til nøyaktig posisjon"</string>
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Bruk nøyaktig posisjon"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Når nøyaktig posisjon er av, har apper tilgang til den omtrentlige posisjonen din"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Tillatelse: <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"<xliff:g id="PERM">%1$s</xliff:g>: tilgang for denne appen"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Tilgang for denne appen: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<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>
@@ -397,7 +397,7 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og får tilgang til Telefon, SMS, kontakter og Kalender."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> får tillatelse til å samhandle med varslene dine og strømme appene dine til den tilkoblede enheten."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Denne tjenesten deler bildene, mediene og varslene dine fra telefonen din til andre enheter."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"Standard notatapper"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"Standard notatapp"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Notatapp"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Apper du kan bruke til å ta notater på enheten"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notater"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Vis aktivering av assistenten"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Vis ikon i statusfeltet når mikrofonen brukes til å aktivere taleassistent"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til bilder og medier på enheten din?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til kontaktene dine?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til denne enhetens posisjon?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Appen får bare tilgang til posisjonen når du bruker appen"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til denne enhetens posisjon?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Denne appen vil kanskje ha tilgang til posisjonen din hele tiden, selv når du ikke bruker appen. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vil du endre posisjonstilgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Denne appen vil ha tilgang til posisjonen din hele tiden, selv når du ikke bruker appen. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tillatelse til å finne, koble til og fastslå den relative posisjonen til enheter i nærheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tillatelse til å finne, koble til og fastslå den relative posisjonen til enheter i nærheten? "<annotation id="link">"Tillat i innstillingene."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Vil du endre posisjontilgangen til <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> fra omtrentlig til nøyaktig?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til denne enhetens omtrentlige posisjon?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Nøyaktig"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Omtrentlig"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til kalenderen din?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sende og se tekstmeldinger?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til bilder, medier og filer på enheten din?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bruke &lt;b&gt;bilder, videoer, musikk og lyd&lt;/b&gt; på denne enheten?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bruke &lt;b&gt;bilder, videoer, musikk, lyd og andre filer&lt;/b&gt; på denne enheten?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bruke musikk og lyd på denne enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bruke bilder og videoer på denne enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; bruke flere bilder og videoer på denne enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta opp lyd?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Appen kan bare ta opp lyd mens du bruker den."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta opp lyd?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Denne appen vil kanskje ta opp lyd hele tiden, selv når du ikke bruker den. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vil du endre mikrofontilgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Denne appen vil ta opp lyd hele tiden, selv når du ikke bruker den. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vil du gi &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilgang til den fysiske aktiviteten din?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta bilder og spille inn video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Appen kan bare ta bilder og spille inn videoer mens du bruker den"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta bilder og spille inn videoer?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Denne appen vil kanskje ta bilder og spille inn videoer hele tiden, selv når du ikke bruker den. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vil du endre kameratilgang for &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Denne appen vil ta bilder og spille inn videoer hele tiden, selv når du ikke bruker den. "<annotation id="link">"Gi tillatelse i innstillingene."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrollerte tillatelser"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrollerte tillatelser"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> har posisjonstilgang"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organisasjonen din lar <xliff:g id="APP_NAME">%1$s</xliff:g> se hvor du er"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Andre tillatelser"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Tillatelser som brukes av systemet"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Tillatelser som bare brukes av systemappene."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Denne appen har oppgitt at den kan dele posisjonsdata med tredjeparter"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datadeling og posisjon"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Hvor kommer informasjon om datadeling fra?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Utvikleren har gitt produsenten av denne enheten informasjon om hvordan denne appen deler data. Utvikleren kan oppdatere denne informasjonen over tid."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Utvikleren har gitt informasjon til "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" om hvordan denne appen deler data. Utvikleren kan oppdatere denne informasjonen over tid."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Denne appen kan dele posisjonsdata for"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datadeling varierer"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datasikkerhet"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Posisjonsdata kan deles"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Denne appen har oppgitt at den kan dele posisjonsdataene dine med tredjeparter"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Kan ikke åpne denne linken"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Oppdatering av datadeling for posisjon"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Gjennomgå apper som har endret hvordan de deler posisjonsdataene dine"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Disse appene har endret hvordan de kan dele posisjonsdataene dine. De har muligens ikke delt dem før eller kan nå dele dem for annonsering eller markedsføring."</string>
diff --git a/PermissionController/res/values-ne-v33/strings.xml b/PermissionController/res/values-ne-v33/strings.xml
index eea107bfb..b16622bd0 100644
--- a/PermissionController/res/values-ne-v33/strings.xml
+++ b/PermissionController/res/values-ne-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"थप अलर्टहरू"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"खारेज गरिएका अलर्टहरू"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{एक्स्पान्ड गरेर थप एउटा अलर्ट हेर्नुहोस्}other{एक्स्पान्ड गरेर थप # वटा अलर्ट हेर्नुहोस्}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"सतर्कता अपनाउनुहोस्। <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"यो कार्य पूरा भएको छ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"तपाईंको डिभाइस थप सुरक्षित गर्न सक्ने सेटिङ जाँच्नुहोस्"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"सुरक्षा तथा गोपनीयतासम्बन्धी द्रुत सेटिङ"</string>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index 001b72f09..bc11bb05e 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -32,11 +32,11 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"“एप प्रयोगमा भएको बेलामा” शीर्षक कायम राख्नुहोस्"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“यस बेला मात्र” राख्नुहोस्"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"थप जानकारी"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"सबै अनुमति दिनुहोस्"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"सबै डेटा प्रयोग गर्ने अनुमति दिनुहोस्"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"सधैँ सबै अनुमति दिइयोस्"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"फोटो र भिडियोहरू चयन गर्नुहोस्"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"अझ धेरै फोटो चयन गर्नुहोस्"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"थप फोटो वा कन्ट्याक्ट चयन नगर्नुहोस्"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"थप डेटा चयन नगर्नुहोस्"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"जे भए पनि फेरि नसोध्नुहोस्"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"खारेज गर्नुहोस्"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> मध्ये <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{आज}=1{१ दिनअघि}other{# दिनअघि}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"एप असक्षम पार्नुहोस्"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"तपाईंले यो एप असक्षम पार्नुभयो भने Android र अन्य एपहरूले अब उप्रान्त अपेक्षाअनुसार कार्य नगर्न सक्छन्। स्मरण रहोस्, तपाईं यो एप तपाईंको यन्त्रसँग पहिल्यै स्थापना भएर आएको हुँदा तपाईं यसलाई मेटाउन सक्नुहुन्न। यो एप असक्षम पारेर, तपाईं यसलाई निष्क्रिय पार्नुहुन्छ तथा यसलाई आफ्नो डिभाइसमा लुकाउनुहुन्छ।"</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"पर्मिसन म्यानेजर"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"अनुमति व्यवस्थापन"</string>
<string name="never_ask_again" msgid="4728762438198560329">"फेरि नसोध्नुहोला"</string>
<string name="no_permissions" msgid="3881676756371148563">"अनुमति दिन भनी कुनै अनुरोध छैन"</string>
<string name="additional_permissions" msgid="5801285469338873430">"अतिरिक्त अनुमति"</string>
@@ -366,7 +366,7 @@
<string name="role_sms_description" msgid="3424020199148153513">"तपाईंलाई छोटा टेक्स्ट म्यासेज, फोटो, भिडियो र थप कुरा पठाउन र प्राप्त गर्न आफ्नो फोन नम्बर प्रयोग गर्न दिने एपहरू"</string>
<string name="role_sms_request_title" msgid="7953552109601185602">"आफ्नो डिफल्ट SMS एपका रूपमा <xliff:g id="APP_NAME">%1$s</xliff:g> सेट गर्ने हो?"</string>
<string name="role_sms_request_description" msgid="2691004766132144886">"यो एपलाई क्यामेरा, कन्ट्याक्ट, फाइल तथा मिडिया, माइक्रोफोन, फोन र SMS हेर्ने तथा प्रयोग गर्ने अनुमति दिइने छ"</string>
- <string name="role_sms_search_keywords" msgid="8022048144395047352">"टेक्स्ट म्यासेज, टेक्स्ट म्यासेज पठाउने, सन्देशहरू, सन्देश प्रवाह"</string>
+ <string name="role_sms_search_keywords" msgid="8022048144395047352">"टेक्स्ट म्यासेज, टेक्स्ट म्यासेज पठाउने, म्यासेजहरू, सन्देश प्रवाह"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"डिफल्ट आपत्‌कालीन एप"</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"आपत्‌कालीन एप"</string>
<string name="role_emergency_description" msgid="5051840234887686630">"तपाईंलाई आफ्नो स्वास्थ्यसम्बन्धी जानकारी रेकर्ड गर्न र आपत्‌कालीन अवस्थामा सहयोग गर्ने मान्छेहरूलाई उक्त जानकारीमाथि पहुँच प्रदान गर्न; कठोर मौसम तथा विपत्तिसम्बन्धी अलर्टहरू प्रदान गर्न; तपाईंलाई आवश्यकता पर्दा अरू मान्छेहरूलाई जानकारी दिन अनुमति दिने एपहरू"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"सहायक ट्रिगर भएको पत्ता लागेमा देखाउनुहोस्"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"आवाज सहायक सक्रिय गर्न माइक्रोफोनको प्रयोग गरिँदा स्टाटस बारमा आइकन देखाउनुहोस्"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्नो डिभाइसका फोटो र मिडियामाथि पहुँच राख्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई कन्ट्याक्ट प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसको लोकेसन प्रयोग दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"तपाईंले एप प्रयोग गरिरहेका बेला मात्र उक्त एपले स्थानमाथि पहुँच राख्न सक्ने छ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसको लोकेसन प्रयोग दिने हो?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"तपाईं उक्त एप प्रयोग नगरिरहेका बेलामा लगायत जुनसुकै समयमा यो एपले तपाईंको स्थानमाथि पहुँच राख्न सक्छ। "<annotation id="link">"सेटिङमा गई अनुमति दिनुहोस्।"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; का लागि स्थानसम्बन्धी पहुँच परिवर्तन गर्ने हो?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"तपाईं उक्त एप प्रयोग नगरिरहेका बेलामा लगायत जुनसुकै समयमा यो एपले तपाईंको स्थानमाथि पहुँच राख्न खोज्छ। "<annotation id="link">"सेटिङमा गई अनुमति दिनुहोस्।"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई नजिकै रहेका डिभाइसहरू भेट्टाउने, ती डिभाइससँग कनेक्ट गर्ने र तिनको सापेक्ष स्थिति निर्धारण गर्ने अनुमति दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई नजिकै रहेका डिभाइसहरू भेट्टाउने, ती डिभाइससँग कनेक्ट गर्ने र तिनको सापेक्ष स्थिति निर्धारण गर्ने अनुमति दिने हो? "<annotation id="link">"सेटिङमा गई अनुमति दिनुहोस्।"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> लाई अनुमानित लोकेसनको साटो सटीक लोकेसन प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसको अनुमानित लोकेसन प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"सटीक"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"अनुमानित"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्नो पात्रोमाथि पहुँच राख्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; SMS म्यासेज पठाउन र हेर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्नो डिभाइसमा रहेका फोटो, मिडिया र फाइलहरू प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसमा रहेका &lt;b&gt;फोटो, भिडियो, सङ्गीत र अडियो&lt;/b&gt; प्रयोग गर्न दिने हो?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसमा रहेका &lt;b&gt;फोटो, भिडियो, सङ्गीत, अडियो तथा अन्य फाइलहरू&lt;/b&gt; प्रयोग गर्न दिने हो?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यस डिभाइसमा रहेका सङ्गीत तथा अन्य अडियो फाइलहरू प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यस डिभाइसमा रहेका फोटो र भिडियोहरू प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई यो डिभाइसमा भएका थप फोटो तथा भिडियोहरू प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई अडियो रेकर्ड गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"तपाईंले यो एप प्रयोग गरिरहेका बेलामा मात्र यसले अडियो रेकर्ड गर्न सक्ने छ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई अडियो रेकर्ड गर्न दिने हो?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"तपाईंले यो एप प्रयोग नगरेका बेलामा पनि यसले अडियो रेकर्ड गर्न सक्छ। "<annotation id="link">"सेटिङमा गई यो अनुमति दिनुहोस्।"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई माइक्रोफोन प्रयोग गर्न दिइएको अनुमति परिवर्तन गर्ने हो?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"तपाईंले यो एप प्रयोग नगरेका बेलामा पनि यसले अडियो रेकर्ड गर्न चाहन्छ। "<annotation id="link">"सेटिङमा गई यो अनुमति दिनुहोस्।"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्नो शारीरिक क्रियाकलाप प्रयोग गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई फोटो खिच्न र भिडियो रेकर्ड गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"तपाईंले यो एप प्रयोग गरिरहेका बेलामा मात्र यसले फोटो खिच्न र भिडियो रेकर्ड गर्न सक्ने छ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई फोटो खिच्न र भिडियो रेकर्ड गर्न दिने हो?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"तपाईंले यो एप प्रयोग नगरेका बेलामा पनि यसले फोटो खिच्न तथा भिडियो रेकर्ड गर्न सक्छ। "<annotation id="link">"सेटिङमा गई यो अनुमति दिनुहोस्।"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई क्यामेरा प्रयोग गर्न दिइएको अनुमति परिवर्तन गर्ने हो?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"तपाईंले यो एप प्रयोग नगरेका बेलामा पनि यसले फोटो खिच्न तथा भिडियो रेकर्ड गर्न चाहन्छ। "<annotation id="link">"सेटिङमा गई यो अनुमति दिनुहोस्।"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई आफ्ना कल लग प्रयोग गर्ने अनुमति दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई फोन कल गर्न र ती कलको व्यवस्थापन गर्न दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई नाडी आदि जस्ता महत्त्वपूर्ण संकेतसम्बन्धी सेन्सर डेटा हेर्ने अनुमति दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"यो एपलाई जुनसुकै बेला (तपाईंले एप नचलाएका बेलासमेत) बडी सेन्सरसम्बन्धी डेटा हेर्न र प्रयोग गर्न दिन "<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="auto_granted_permissions" msgid="6009452264824455892">"नियन्त्रित अनुमतिहरू"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंलाई सूचना पठाउन दिने हो?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"नियन्त्रित अनुमतिहरू"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई लोकेसन प्रयोग गर्ने अनुमति दिइएको छ"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"तपाईंको सङ्गठनले <xliff:g id="APP_NAME">%1$s</xliff:g> लाई तपाईंको लोकेसन प्रयोग गर्ने अनुमति दिएको छ"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"अन्य अनुमतिहरू"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">" सिस्टमले प्रयोग गर्ने अनुमतिहरू"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"सिस्टमका एपहरूमा मात्र प्रयोग गरिने अनुमतिहरू।"</string>
@@ -577,7 +629,7 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"ब्याकग्राउन्डमा लोकेसन प्रयोग गर्ने अनुमति दिइएको एपको समीक्षा गर्नुहोस्"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"यो एप बन्द हुँदा पनि यसले जुनसुकै बेला तपाईंको लोकेसन प्रयोग गर्न सक्छ।\n\nसुरक्षा तथा आपत्कालीन प्रयोजनका लागि बनाइएका केही एपहरूले राम्रोसँग काम गर्नका निम्ति तपाईंले ती एपहरूलाई ब्याकग्राउन्डमा तपाईंको लोकेसन प्रयोग गर्ने अनुमति दिनु पर्ने हुन्छ।"</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"अनुमति बदलियो"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"हालसालै प्रयोग गरिएको लोकेसनसम्बन्धी जानकारी हेर्नुहोस्"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"हालसालै कहिले लोकेसनसम्बन्धी प्रयोग गरिएको थियो हेर्नुहोस्"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"गोपनीयतासम्बन्धी सेटिङ"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"क्यामेरा प्रयोग गर्ने अनुमति"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"माइक्रोफोन प्रयोग गर्ने अनुमति"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"यो एपले यसले लोकेसन डेटा तेस्रो पक्षसँग सेयर गर्न सक्छ भन्ने जानकारी दिएको छ"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"लोकेसन डेटा सेयर गर्नेसम्बन्धी अभ्यास"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"जानकारी सेयर गर्नेसम्बन्धी अभ्यासको स्रोत"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"यो एपका विकासकर्ताले यो एपले जानकारी सेयर गर्ने तरिकाका बारेमा यो डिभाइसका उत्पादकलाई जानकारी दिएका छन्। ती विकासकर्ता भविष्यमा उक्त जानकारी संशोधन गर्न सक्छन्।"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"यो एपका विकासकर्ताले यो एपले जानकारी सेयर गर्ने तरिकाका बारेमा "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" लाई जानकारी दिएका छन्। ती विकासकर्ता समय क्रममा उक्त जानकारी संशोधन गर्न सक्छन्।"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"यो एपले निम्न प्रयोजनका लागि लोकेसन सेयर गर्न सक्छ:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"जानकारी सेयर गर्नेसम्बन्धी अभ्यास फरक हुन सक्छ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"जानकारीको सुरक्षा"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"लोकेसन डेटा सेयर गरिन सक्छ"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"यो एपले यसले तपाईंको लोकेसन डेटा तेस्रो पक्षसँग सेयर गर्न सक्छ भन्ने जानकारी दिएको छ"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"यो लिंक खोल्न सकिएन"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"लोकेसन डेटा सेयर गर्नेसम्बन्धी अभ्यासका बारेमा अद्यावधिक जानकारी"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"तपाईंको लोकेसन डेटा सेयर गर्न सक्ने तरिका परिवर्तन गरेका एपहरूको समीक्षा गर्नुहोस्"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"यी एपहरूले तपाईंको लोकेसन डेटा सेयर गर्न सक्ने तरिका परिवर्तन गरेका छन्। यी एपहरूले यसअघि तपाईंको लोकेसन डेटा सेयर नगरेका हुन सक्छन् तर अब भने विज्ञापन तथा मार्केटिङ गर्ने प्रयोजनका लागि तपाईंको लोकेसन डेटा सेयर गर्न सक्छन्।"</string>
diff --git a/PermissionController/res/values-night-v33/themes.xml b/PermissionController/res/values-night-v33/themes.xml
index 6374ee088..9b6f638a6 100644
--- a/PermissionController/res/values-night-v33/themes.xml
+++ b/PermissionController/res/values-night-v33/themes.xml
@@ -16,10 +16,6 @@
-->
<resources>
- <style name="Theme.SafetyCenterQs" parent="Theme.SafetyCenterQsBase">
- <item name="textColorScSecondaryActionButton">?android:attr/textColorPrimary</item>
- </style>
-
<style name="Theme.SafetyCenterBase" parent="Theme.PermissionController.Settings.FilterTouches">
<item name="colorSurface">@color/sc_surface_dark</item>
<item name="colorSurfaceVariant">@color/sc_surface_variant_dark</item>
@@ -49,8 +45,12 @@
<item name="scStatusButtonStyle">@style/SafetyCenterStatusButton.Responsive</item>
<!-- Buttons -->
- <item name="scActionButtonStyle">@style/SafetyCenterActionButton</item>
- <item name="scSecondaryActionButtonStyle">@style/SafetyCenterActionButton.Secondary</item>
+ <item name="scActionButtonListLayout">@layout/action_button_list_responsive</item>
+ <item name="scActionButtonTheme">@style/Theme.MaterialComponents.DayNight</item>
+ <item name="scActionButtonStyle">@style/SafetyCenterActionButton.Responsive</item>
+ <item name="scSecondaryActionButtonStyle">
+ @style/SecondarySafetyCenterActionButton.Responsive
+ </item>
<item name="textColorScActionButton">@color/sc_primary_action_button_text</item>
<item name="textColorScSecondaryActionButton">?android:attr/textColorPrimary</item>
diff --git a/PermissionController/res/values-night-v34/themes.xml b/PermissionController/res/values-night-v34/themes.xml
index affc57027..b6328d782 100644
--- a/PermissionController/res/values-night-v34/themes.xml
+++ b/PermissionController/res/values-night-v34/themes.xml
@@ -21,11 +21,6 @@
<item name="android:colorBackground">@color/google_grey_800</item>
</style>
- <style name="Theme.SafetyCenterQs" parent="Theme.SafetyCenterQsBase">
- <item name="textColorScSecondaryActionButton">?android:attr/textColorPrimary</item>
- <item name="colorScShieldAccent">@color/sc_shield_accent_dark</item>
- </style>
-
<style name="Theme.SafetyCenter" parent="Theme.SafetyCenterBase">
<item name="colorScShieldAccent">@color/sc_shield_accent_dark</item>
</style>
diff --git a/PermissionController/res/values-nl-v33/strings.xml b/PermissionController/res/values-nl-v33/strings.xml
index df5ad6a15..5b89f1135 100644
--- a/PermissionController/res/values-nl-v33/strings.xml
+++ b/PermissionController/res/values-nl-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Meer meldingen"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Gesloten meldingen"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Uitvouwen en nog 1 melding bekijken}other{Uitvouwen en nog # meldingen bekijken}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Waarschuwing. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Actie afgerond"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Check de instellingen die je apparaat beter kunnen beschermen"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Snelle instellingen voor beveiliging en privacy"</string>
diff --git a/PermissionController/res/values-nl-v34/strings.xml b/PermissionController/res/values-nl-v34/strings.xml
index a695de975..b3265d254 100644
--- a/PermissionController/res/values-nl-v34/strings.xml
+++ b/PermissionController/res/values-nl-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Beveiliging en privacy"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Bediening"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Toegang van app tot gezondheidsgegevens beheren"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Beheer de toegang van apps tot je gezondheidsgegevens"</string>
<string name="location_settings" msgid="8863940440881290182">"Locatietoegang"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Voor apps en services. Als deze instelling uitstaat, kunnen microfoongegevens nog altijd worden gedeeld als je een alarmnummer belt."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Voor apps en services"</string>
diff --git a/PermissionController/res/values-nl/strings.xml b/PermissionController/res/values-nl/strings.xml
index e7c8a81b0..f05f705de 100644
--- a/PermissionController/res/values-nl/strings.xml
+++ b/PermissionController/res/values-nl/strings.xml
@@ -41,7 +41,7 @@
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Sluiten"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> van <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; het volgende toestaan: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; altijd toestaan om <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; altijd het volgende toestaan: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Alleen als app in gebruik is"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Altijd"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Niet toestaan en niet meer vragen"</string>
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Vandaag}=1{1 dag geleden}other{# dagen geleden}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"App uitzetten"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Als je deze app uitzet, werken Android en andere apps mogelijk niet meer zoals bedoeld. Je kunt deze app niet verwijderen omdat deze vooraf geïnstalleerd was op je apparaat. Door de app uit te zetten verberg je deze ook op je apparaat."</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"Rechtenbeheer"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"Rechten­beheer"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Niet meer vragen"</string>
<string name="no_permissions" msgid="3881676756371148563">"Geen rechten"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Aanvullende rechten"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Altijd toestaan"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Toestaan bij gebruik van app"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Alleen toestaan bij gebruik van app"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Niet toestaan"</string>
<string name="loading" msgid="4789365003890741082">"Laden…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Alle rechten"</string>
@@ -195,7 +195,7 @@
<string name="approximate_image_description" msgid="938803699637069884">"Geschatte locatie"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Exacte locatie gebruiken"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Als de exacte locatie uitstaat, hebben apps toegang tot je geschatte locatie"</string>
- <string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>-rechten"</string>
+ <string name="app_permission_title" msgid="2090897901051370711">"Rechten: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Toegang tot <xliff:g id="PERM">%1$s</xliff:g> voor deze app"</string>
<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>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Activeringsdetectie van de assistent tonen"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Icoon op statusbalk tonen als microfoon wordt gebruikt om de Spraakassistent te activeren"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot foto\'s en media op je apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je contacten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot de locatie van dit apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"De app heeft alleen toegang tot de locatie wanneer je de app gebruikt"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot de locatie van dit apparaat?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Deze app wil mogelijk altijd toegang tot je locatie, ook als je de app niet gebruikt. "<annotation id="link">"Je kunt dit toestaan via de instellingen."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Toegang tot locatie wijzigen voor &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Deze app wil altijd toegang tot je locatie, ook als je de app niet gebruikt. "<annotation id="link">"Je kunt dit toestaan via de instellingen."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; apparaten in de buurt vindt, er verbinding mee maakt en de relatieve positie bepaalt?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; apparaten in de buurt vindt, er verbinding mee maakt en de relatieve positie bepaalt? "<annotation id="link">"Toestaan in Instellingen"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Locatietoegang van <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> wijzigen van geschatte in exacte locatie?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot de geschatte locatie van dit apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exact"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Geschat"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je agenda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om sms\'jes te verzenden en te bekijken?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot foto\'s, media en bestanden op je apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot &lt;b&gt;foto\'s, video\'s, muziek en audio&lt;/b&gt; op dit apparaat?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot &lt;b&gt;foto\'s, video\'s, muziek, audio en andere bestanden&lt;/b&gt; op dit apparaat?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot muziek en audio op dit apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot foto\'s en video\'s op dit apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot meer foto\'s en video\'s op dit apparaat?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om audio op te nemen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Deze app kan alleen audio opnemen als je de app gebruikt"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om audio op te nemen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Deze app wil mogelijk altijd audio opnemen, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in instellingen."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Toegang tot microfoon wijzigen voor &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Deze app wil altijd audio opnemen, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in instellingen."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toegang geven tot je fysieke activiteit?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om foto\'s te maken en video\'s op te nemen?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Deze app kan alleen foto\'s maken en video\'s opnemen als je de app gebruikt"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om foto\'s te maken en video\'s op te nemen?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Deze app wil mogelijk altijd foto\'s maken en video\'s opnemen, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in Instellingen."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Toegang tot camera wijzigen voor &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Deze app wil altijd foto\'s maken en video\'s opnemen, ook als je de app niet gebruikt. "<annotation id="link">"Toestaan in Instellingen."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Deze app wil altijd toegang tot gegevens van lichaamssensoren over 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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Als je deze app altijd toegang tot gegevens van lichaamssensoren wilt geven, ook als je de app niet gebruikt, "<annotation id="link">"ga je naar Instellingen"</annotation>"."</string>
<string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Instelling behouden 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; je meldingen stuurt?"</string>
- <string name="auto_granted_permissions" msgid="6009452264824455892">"Beheerde rechten"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; je meldingen stuurt?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Beheerde rechten"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> heeft toegang tot je locatie"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Je organisatie geeft <xliff:g id="APP_NAME">%1$s</xliff:g> toegang tot je locatie"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Overige rechten"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Recht gebruikt door het systeem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Rechten alleen gebruikt door systeem-apps."</string>
@@ -572,9 +624,9 @@
<string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Deze app ondersteunt de nieuwste versie van Android niet. Als deze app geen toegang heeft tot muziek- en audiobestanden, heeft deze ook geen toegang tot foto\'s en video\'s."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Deze app ondersteunt de nieuwste versie van Android niet. Als deze app toegang heeft tot foto\'s en video\'s, heeft deze ook toegang tot muziek- en audiobestanden."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Deze app ondersteunt de nieuwste versie van Android niet. Als deze app geen toegang heeft tot muziek- en audiobestanden, heeft deze ook geen toegang tot foto\'s en video\'s."</string>
- <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Apps met toegang tot locatie op de achtergrond bekijken"</string>
+ <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"App met toegang tot locatie op de achtergrond doornemen"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> heeft altijd toegang tot je locatie, ook als de app gesloten is"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Apps met toegang tot locatie op de achtergrond bekijken"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"App met toegang tot locatie op de achtergrond doornemen"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Deze app heeft altijd toegang tot je locatie, ook als de app gesloten is.\n\nBepaalde veiligheids- en nood-apps hebben op de achtergrond toegang tot je locatie nodig voor een juiste werking."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Toegang gewijzigd"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Recent locatiegebruik bekijken"</string>
@@ -587,10 +639,11 @@
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Toegang tot klembord tonen"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Toon een bericht als apps toegang hebben tot tekst, afbeeldingen of andere content die je hebt gekopieerd"</string>
<string name="show_password_title" msgid="2877269286984684659">"Wachtwoorden tonen"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Tekens kort tonen terwijl je typt"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Geef tekens kort weer terwijl je typt"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Deze app geeft aan dat locatiegegevens kunnen worden gedeeld met derden"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Gegevens delen en locatie"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Waar informatie over gegevens delen vandaan komt"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"De ontwikkelaar heeft de fabrikant van het apparaat informatie gegeven over de manier waarop deze app gegevens deelt. De ontwikkelaar kan deze informatie in de loop van de tijd updaten."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"De ontwikkelaar heeft informatie gegeven aan "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" over hoe deze app gegevens deelt. De ontwikkelaar kan deze informatie in de loop van de tijd updaten."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Deze app kan locatiegegevens delen voor:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Gegevens delen verschilt"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Veiligheid van gegevens"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Locatiegegevens kunnen worden gedeeld"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Deze app geeft aan dat je locatiegegevens met derden kunnen worden gedeeld"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Link kan niet worden geopend"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Updates voor het delen van locatiegegevens"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Check apps die de manier hebben veranderd waarop je locatiegegevens worden gedeeld"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Deze apps hebben de manier veranderd waarop ze je locatiegegevens kunnen delen. Misschien deelden ze de gegevens eerder niet, of kunnen ze deze nu delen voor reclame- en marketingdoeleinden."</string>
diff --git a/PermissionController/res/values-or-v33/strings.xml b/PermissionController/res/values-or-v33/strings.xml
index 21b7042f4..84c07b84e 100644
--- a/PermissionController/res/values-or-v33/strings.xml
+++ b/PermissionController/res/values-or-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ଅଧିକ ଆଲର୍ଟ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ଖାରଜ କରାଯାଇଥିବା ଆଲର୍ଟଗୁଡ଼ିକ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ବିସ୍ତାର କରି ଆଉ ଗୋଟିଏ ଆଲର୍ଟ ଦେଖନ୍ତୁ}other{ବିସ୍ତାର କରି ଆଉ #ଟି ଆଲର୍ଟ ଦେଖନ୍ତୁ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ଆଲର୍ଟ। <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"କାର୍ଯ୍ୟ ସମୂର୍ଣ୍ଣ ହୋଇଛି"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ଆପଣଙ୍କ ଡିଭାଇସରେ ସୁରକ୍ଷା ଯୋଗ କରୁଥିବା ସେଟିଂସକୁ ଦେଖନ୍ତୁ"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"ସୁରକ୍ଷା ଏବଂ ଗୋପନୀୟତା କ୍ୱିକ ସେଟିଂସ"</string>
diff --git a/PermissionController/res/values-or-v34/strings.xml b/PermissionController/res/values-or-v34/strings.xml
index dab5f74f9..2994a3f25 100644
--- a/PermissionController/res/values-or-v34/strings.xml
+++ b/PermissionController/res/values-or-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"ସୁରକ୍ଷା ଏବଂ ଗୋପନୀୟତା"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"ସ୍ୱାସ୍ଥ୍ୟ ଡାଟାକୁ ଆପର ଆକ୍ସେସକୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"ସ୍ୱାସ୍ଥ୍ୟ ଡାଟା ପାଇଁ ଆପର ଆକ୍ସେସକୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="location_settings" msgid="8863940440881290182">"ଲୋକେସନ ଆକ୍ସେସ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ। ଯଦି ଏହି ସେଟିଂ ବନ୍ଦ ଥାଏ, ତେବେ ଆପଣ ଏକ ଜରୁରୀକାଳୀନ ନମ୍ବରକୁ କଲ କରିବା ସମୟରେ ମାଇକ୍ରୋଫୋନ ଡାଟା ଏବେ ବି ସେୟାର କରାଯାଇପାରେ"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ"</string>
diff --git a/PermissionController/res/values-or-watch/strings.xml b/PermissionController/res/values-or-watch/strings.xml
index b5c17dbb0..ef9515f25 100644
--- a/PermissionController/res/values-or-watch/strings.xml
+++ b/PermissionController/res/values-or-watch/strings.xml
@@ -21,5 +21,5 @@
<string name="preference_show_system_apps" msgid="1055740303992024300">"ସିଷ୍ଟମ୍‍ ଆପ୍ସ ଦେଖାନ୍ତୁ"</string>
<string name="permission_summary_enforced_by_policy" msgid="2352478756952948019">"ଏହା ବଦଳାଯାଇପାରିବ ନାହିଁ"</string>
<string name="generic_yes" msgid="2489207724988649846">"ହଁ"</string>
- <string name="generic_cancel" msgid="2631708607129269698">"ବାତିଲ"</string>
+ <string name="generic_cancel" msgid="2631708607129269698">"ବାତିଲ କରନ୍ତୁ"</string>
</resources>
diff --git a/PermissionController/res/values-or/strings.xml b/PermissionController/res/values-or/strings.xml
index e56b39141..a6bf5ae92 100644
--- a/PermissionController/res/values-or/strings.xml
+++ b/PermissionController/res/values-or/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"ଯେ କୌଣସି ମତେ ଅନୁମତି ଦିଅ ନାହିଁ"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"ଖାରଜ କରନ୍ତୁ"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> ରୁ <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ <xliff:g id="ACTION">%2$s</xliff:g> ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ସବୁବେଳେ <xliff:g id="ACTION">%2$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ <xliff:g id="ACTION">%2$s</xliff:g> ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ସବୁବେଳେ <xliff:g id="ACTION">%2$s</xliff:g> ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"କେବଳ ଆପ୍‍ ବ୍ୟବହାର ସମୟରେ"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"ସର୍ବଦା"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ ଏବଂ ପୁଣି ପଚାରନ୍ତୁ ନାହିଁ"</string>
@@ -59,7 +59,7 @@
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"ମିଡିଆ ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"ଆପ୍ସ"</string>
<string name="app_permissions" msgid="3369917736607944781">"ଆପ ଅନୁମତିଗୁଡ଼ିକ"</string>
- <string name="unused_apps" msgid="2058057455175955094">"ଅବ୍ୟବହୃତ ଆପଗୁଡ଼ିକ"</string>
+ <string name="unused_apps" msgid="2058057455175955094">"ଅବ୍ୟବହୃତ ଆପ୍ସ"</string>
<string name="no_unused_apps" msgid="12809387670415295">"କୌଣସି ଅବ୍ୟବହୃତ ଆପ୍ ନାହିଁ"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"0ଟି ଅବ୍ୟବହୃତ ଆପ୍"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"ବର୍ତ୍ତମାନର ଅନୁମତି ନିଷ୍ପତ୍ତି"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"ସର୍ବଦା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"ଆପ୍ ବ୍ୟବହାର ବେଳେ କେବଳ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"ଆପ ବ୍ୟବହାର ବେଳେ କେବଳ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="permission_access_never" msgid="4647014230217936900">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
<string name="loading" msgid="4789365003890741082">"ଲୋଡ୍ ହେଉଛି…"</string>
<string name="all_permissions" msgid="6911125611996872522">"ସମସ୍ତ ଅନୁମତିଗୁଡ଼ିକ"</string>
@@ -124,7 +124,7 @@
<string name="current_permissions_category" msgid="4292990083585728880">"ବର୍ତ୍ତମାନର ଅନୁମତିଗୁଡ଼ିକ"</string>
<string name="message_staging" msgid="9110563899955511866">"ଆପ୍‍ ପର୍ଯ୍ୟାୟଭୁକ୍ତ କରାଯାଉଛି…"</string>
<string name="app_name_unknown" msgid="1319665005754048952">"ଅଜଣା"</string>
- <string name="permission_usage_title" msgid="1568233336351734538">"ଗୋପନୀୟତା ଡ୍ୟାସବୋର୍ଡ"</string>
+ <string name="permission_usage_title" msgid="1568233336351734538">"ଗୋପନୀୟତା ଡେସବୋର୍ଡ"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"କେଉଁ ଆପଗୁଡ଼ିକ ଏବେ ଅନୁମତିଗୁଡ଼ିକ ବ୍ୟବହାର କରିଛି ତାହା ଦେଖନ୍ତୁ"</string>
<string name="permission_group_usage_title" msgid="2595013198075285173">"<xliff:g id="PERMGROUP">%1$s</xliff:g> ବ୍ୟବହାର"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"ଅନ୍ୟ ଅନୁମତିଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string>
@@ -187,7 +187,7 @@
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"ସମସ୍ତ ଫାଇଲର ପରିଚାଳନା ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"କେବଳ ମିଡିଆକୁ ଆକ୍ସେସ୍ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="app_permission_button_allow_always" msgid="4573292371734011171">"ସବୁ ସମୟ ପାଇଁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
- <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"ଆପ୍ ବ୍ୟବହାର ବେଳେ କେବଳ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="app_permission_button_allow_foreground" msgid="1991570451498943207">"ଆପ ବ୍ୟବହାର ବେଳେ କେବଳ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="app_permission_button_always_allow_all" msgid="4905699259378428855">"ସର୍ବଦା ସବୁକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
<string name="app_permission_button_ask" msgid="3342950658789427">"ପ୍ରତ୍ୟେକ ଥର ପଚାରନ୍ତୁ"</string>
<string name="app_permission_button_deny" msgid="6016454069832050300">"ଅନୁମତି ଦିଅନ୍ତୁ ନାହିଁ"</string>
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"ସଠିକ୍ ଲୋକେସନ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"ଯେତେବେଳେ ସଠିକ୍ ଲୋକେସନ୍ ବନ୍ଦ ଥାଏ, ସେତେବେଳେ ଆପଗୁଡ଼ିକ ଆପଣଙ୍କ ଆନୁମାନିକ ଲୋକେସନକୁ ଆକ୍ସେସ୍ କରିପାରିବ"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> ଅନୁମତି"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"ଏହି ଆପ ପାଇଁ <xliff:g id="PERM">%1$s</xliff:g> ଆକ୍ସେସକୁ ଅନୁମତି ଦିଅନ୍ତୁ"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"ଏହି ଆପ ପାଇଁ <xliff:g id="PERM">%1$s</xliff:g>ର ଆକ୍ସେସ"</string>
<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>
@@ -218,7 +218,7 @@
<string name="auto_revoked_app_summary_one" msgid="7093213590301252970">"<xliff:g id="PERMISSION_NAME">%s</xliff:g> ଅନୁମତିକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g> ଏବଂ <xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g> ଅନୁମତିକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"<xliff:g id="PERMISSION_NAME">%1$s</xliff:g> ଏବଂ ଅନ୍ୟ <xliff:g id="NUMBER">%2$s</xliff:g>ଟି ଅନୁମତି କାଢ଼ି ଦିଆଯାଇଛି"</string>
- <string name="unused_apps_page_title" msgid="6986983535677572559">"ଅବ୍ୟବହୃତ ଆପଗୁଡ଼ିକ"</string>
+ <string name="unused_apps_page_title" msgid="6986983535677572559">"ଅବ୍ୟବହୃତ ଆପ୍ସ"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"ଯଦି ଏକ ଆପ୍ କିଛି ମାସ ପାଇଁ ଅବ୍ୟବହୃତ ଅଛି, ତେବେ:\n\n• ଆପଣଙ୍କ ଡାଟାକୁ ସୁରକ୍ଷା ଦେବା ପାଇଁ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଏ\n• ବ୍ୟାଟେରୀ ସେଭ୍ କରିବାକୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ବନ୍ଦ କରାଯାଏ\n• ସ୍ପେସ୍ ଖାଲି କରିବା ପାଇଁ ଅସ୍ଥାୟୀ ଫାଇଲଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଏ\n\nଅନୁମତି ଏବଂ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ପୁଣି ଅନୁମତି ଦେବା ପାଇଁ, ଆପ୍ ଖୋଲନ୍ତୁ।"</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"ଯଦି କୌଣସି ଆପକୁ ଏକ ମାସ ପାଇଁ ବ୍ୟବହାର କରାଯାଇନାହିଁ, ତେବେ:\n\n• ଆପଣଙ୍କ ଡାଟାକୁ ସୁରକ୍ଷିତ ରଖିବା ପାଇଁ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଏ\n• ସ୍ପେସ ଖାଲି କରିବା ପାଇଁ ଅସ୍ଥାୟୀ ଫାଇଲଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯାଏ\n\nପୁଣି ଅନୁମତିଗୁଡ଼ିକ ଦେବା ପାଇଁ, ଆପକୁ ଖୋଲନ୍ତୁ।"</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{# ମାସରୁ ଅଧିକ ସମୟ ପୂର୍ବେ ଖୋଲାଯାଇଥିଲା}other{# ମାସରୁ ଅଧିକ ସମୟ ପୂର୍ବେ ଖୋଲାଯାଇଥିଲା}}"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"ଗତ ଥର <xliff:g id="DATE">%s</xliff:g>ରେ ଖୋଲାଯାଇଥିଲା"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"ଯଦି ଆପଣ ସମସ୍ତ ଫାଇଲର ପରିଚାଳନାକୁ ଅନୁମତି ଦିଅନ୍ତି, ତେବେ ଏହି ଆପ୍ ଏ ଡିଭାଇସ୍ କିମ୍ବା ସଂଯୋଗ ହୋଇଥିବା ଷ୍ଟୋରେଜ୍ ଡିଭାଇସର ସାଧାରଣ ଷ୍ଟୋରେଜରେ ଥିବା ଯେ କୌଣସି ଫାଇଲକୁ ଆକ୍ସେସ୍, ପରିବର୍ତ୍ତନ ଏବଂ ଡିଲିଟ୍ କରିପାରିବ। ଆପଟି ଆପଣଙ୍କୁ ନ ପଚାରି ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିପାରେ।"</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"ଏହି ଆପକୁ ଏ ଡିଭାଇସରେ କିମ୍ବା ଯେ କୌଣସି ସଂଯୋଗ ହୋଇଥିବା ଷ୍ଟୋରେଜ୍ ଡିଭାଇସଗୁଡ଼ିକରେ ଥିବା ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍, ପରିବର୍ତ୍ତନ ଏବଂ ଡିଲିଟ୍ କରିବାକୁ ଅନୁମତି ଦେବେ କି? ଏହି ଆପ୍ ଆପଣଙ୍କୁ ନ ପଚାରି ଫାଇଲଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିପାରେ।"</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"ଏହି ଅନୁମତି ଥିବା ଆପ୍ସ <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"ଏହି ଅନୁମତି ଥିବା ଆପ୍ସ ଏହା କରିପାରିବ <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"ଏହି ଅନୁମତି ସହିତ ଆପଗୁଡ଼ିକ, ଚାଲିବା, ବାଇକ୍ ଚଲାଇବା, ଡ୍ରାଇଭିଂ, ଷ୍ଟେପ୍ ଗଣନା ଏବଂ ଆହୁରି ଅନେକ କିଛି ପରି ଆପଣଙ୍କ ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପକୁ ଆକ୍ସେସ୍ କରିପାରିବ"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"ଏହି ଅନୁମତି ଥିବା ଆପ୍ସ ଆପଣଙ୍କର କ୍ୟାଲେଣ୍ଡର୍ ଆକ୍ସେସ୍ କରିପାରିବ"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"ଏହି ଅନୁମତି ଥିବା ଆପ୍‌ଗୁଡ଼ିକ ଫୋନ୍‌ କଲ୍ ଲଗ୍ ପଢ଼ିପାରିବେ ଏବଂ ଲେଖିପାରିବେ"</string>
@@ -302,7 +302,7 @@
<string name="auto_revoke_before_notification_title_one" msgid="6758024954464359876">"1ଟି ଆପ୍ ବ୍ୟବହାର କରାଯାଇନାହିଁ"</string>
<string name="auto_revoke_before_notification_title_many" msgid="4415543943846385685">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g>ଟି ଆପ୍ ବ୍ୟବହାର କରାଯାଇନାହିଁ"</string>
<string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"ଆପଣଙ୍କ ଗୋପନୀୟତାକୁ ସୁରକ୍ଷା ଦେବା ପାଇଁ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଆଯିବ। ସମୀକ୍ଷା କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
- <string name="unused_apps_title" msgid="8589298917717872239">"ଅବ୍ୟବହୃତ ଆପଗୁଡ଼ିକ"</string>
+ <string name="unused_apps_title" msgid="8589298917717872239">"ଅବ୍ୟବହୃତ ଆପ୍ସ"</string>
<string name="unused_apps_subtitle_after" msgid="2034267519506357898">"ଏଥିରୁ ଅନୁମତିଗୁଡ଼ିକ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="unused_apps_subtitle_before" msgid="5233302577076132427">"ଏଥିରୁ ଅନୁମତିଗୁଡ଼ିକ କାଢ଼ି ଦିଆଯିବ"</string>
<string name="unused_permissions_subtitle_two" msgid="2207266295008423015">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g> ଏବଂ <xliff:g id="PERM_NAME_1">%2$s</xliff:g>"</string>
@@ -315,7 +315,7 @@
<string name="permission_subtitle_media_only" msgid="8917869683764720717">"ମିଡିଆ"</string>
<string name="permission_subtitle_all_files" msgid="4982613338298067862">"ସମସ୍ତ ଫାଇଲ୍"</string>
<string name="permission_subtitle_background" msgid="8916750995309083180">"ସର୍ବଦା ଅନୁମତି ଦିଆଯାଇଛି"</string>
- <string name="app_perms_24h_access" msgid="99069906850627181">"<xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ୍ କରାଯାଇଛି"</string>
+ <string name="app_perms_24h_access" msgid="99069906850627181">"<xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ କରାଯାଇଛି"</string>
<string name="app_perms_24h_access_yest" msgid="5411926024794555022">"ଗତକାଲି <xliff:g id="TIME_DATE">%1$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ୍ କରାଯାଇଛି"</string>
<string name="app_perms_7d_access" msgid="4945055548894683751">"<xliff:g id="TIME_DATE_0">%1$s</xliff:g> <xliff:g id="TIME_DATE_1">%2$s</xliff:g>ରେ ଗତଥର ଆକ୍ସେସ କରାଯାଇଛି"</string>
<string name="app_perms_content_provider_24h" msgid="1055526027667508972">"ଗତ 24 ଘଣ୍ଟାରେ ଆକ୍ସେସ କରାଯାଇଛି"</string>
@@ -337,7 +337,7 @@
<string name="app_perms_content_provider_7d_all_files" msgid="7962416229708835558">"ଗତ 7 ଦିନରେ ଆକ୍ସେସ କରାଯାଇଛି • ସମସ୍ତ ଫାଇଲ"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"କୌଣସି ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"କୌଣସି ଅନୁମତି ଅଗ୍ରାହ୍ୟ କରାଯାଇନାହିଁ"</string>
- <string name="no_apps_allowed" msgid="7718822655254468631">"କୌଣସି ଆପକୁ ଅନୁମତି ନାହିଁ"</string>
+ <string name="no_apps_allowed" msgid="7718822655254468631">"କୌଣସି ଆପ୍ସକୁ ଅନୁମତି ନାହିଁ"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"ସମସ୍ତ ଫାଇଲ୍ ପାଇଁ କୌଣସି ଆପକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"କେବଳ ମିଡିଆ ପାଇଁ କୌଣସି ଆପକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
<string name="no_apps_denied" msgid="7663435886986784743">"କୌଣସି ଆପକୁ ଅଗ୍ରାହ୍ୟ କରାଯାଇନାହିଁ"</string>
@@ -426,7 +426,7 @@
<string name="default_apps_more" msgid="4078194675848858093">"ଅଧିକ ଡିଫଲ୍ଟଗୁଡ଼ିକ"</string>
<string name="default_apps_manage_domain_urls" msgid="6775566451561036069">"ଓପନିଂ ଲିଙ୍କ୍"</string>
<string name="default_apps_for_work" msgid="4970308943596201811">"କାର୍ଯ୍ୟ ପାଇଁ ଡିଫଲ୍ଟ ଅଛି"</string>
- <string name="default_app_none" msgid="9084592086808194457">"କିଛି ଆପ୍‌ ସେଟ୍‌ କରାଯାଇନାହିଁ"</string>
+ <string name="default_app_none" msgid="9084592086808194457">"କିଛି ଆପ ସେଟ କରାଯାଇନାହିଁ"</string>
<string name="default_app_system_default" msgid="6218386768175513760">"(ସିଷ୍ଟମ୍ ଡିଫଲ୍ଟ)"</string>
<string name="default_app_no_apps" msgid="115720991680586885">"କୌଣସି ଆପ୍‌ ନାହିଁ"</string>
<string name="car_default_app_selected" msgid="5416420830430644174">"ଚୟନ କରାଯାଇଛି"</string>
@@ -455,59 +455,84 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"ଆସିଷ୍ଟାଣ୍ଟ ଟ୍ରିଗର୍ ଚିହ୍ନଟକରଣ ଦେଖାନ୍ତୁ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ଭଏସ୍ ଆସିଷ୍ଟାଣ୍ଟ୍ ସକ୍ରିୟ କରିବା ପାଇଁ ମାଇକ୍ରୋଫାନ୍ ବ୍ୟବହାର କରୁଥିବା ସମୟରେ ସ୍ଥିତି ବାର୍‌ରେ ଆଇକନ୍ ଦେଖାନ୍ତୁ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"ଆପଣଙ୍କ ଡିଭାଇସ୍‌ରେ ଥିବା ଫଟୋ ଓ ମିଡିଆ ଆକ୍‌ସେସ୍ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
- <string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ ଯୋଗାଯୋଗଗୁଡ଼ିକୁ ଆକ୍ସେସ୍‍ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା ଫଟୋ ଏବଂ ମିଡିଆକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ କଣ୍ଟାକ୍ଟଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା କଣ୍ଟାକ୍ଟଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"ଏହି ଡିଭାଇସର ଲୋକେସନ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>ର&lt;/b&gt; ଲୋକେସନକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ଆପଣ ଆପ୍ ବ୍ୟବହାର କରୁଥିବା ବେଳେ କେବଳ ଲୋକେସନ୍‍କୁ ଆପ୍‍ର ଆକ୍ସେସ୍‍ ରହିବ।"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ଏହି ଡିଭାଇସ୍‌ର ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>ର ଲୋକେସନକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ଆପଣ ଆପ୍ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହି ଆପ୍ ସବୁ ସମୟରେ ଆପଣଙ୍କର ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିବାକୁ ଚାହିଁପାରେ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ ଲୋକେସନ୍ ଆକ୍ସେସ୍ ବଦଳାଇବେ କି?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ ଲୋକେସନ ଆକ୍ସେସକୁ ପରିବର୍ତ୍ତନ କରିବେ?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ଆପଣ ଆପ୍ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହି ଆପ୍ ସବୁ ସମୟରେ ଆପଣଙ୍କର ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିବାକୁ ଚାହେଁ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକର ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ଖୋଜିବା, କନେକ୍ଟ ଏବଂ ନିର୍ଦ୍ଧାରଣ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଆଖପାଖର ଡିଭାଇସର ଆପେକ୍ଷିକ ସ୍ଥିତିକୁ ଖୋଜିବା, କନେକ୍ଟ ଓ ସ୍ଥିର କରିବାକୁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"ଆଖପାଖର ଡିଭାଇସଗୁଡ଼ିକର ଆପେକ୍ଷିକ ଅବସ୍ଥିତିକୁ ଖୋଜିବା, ସଂଯୋଗ ଏବଂ ନିର୍ଦ୍ଧାରଣ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ? "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>ର ଲୋକେସନ୍ ଆକ୍ସେସକୁ ଆନୁମାନିକରୁ ସଠିକକୁ ବଦଳାଇବେ?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>ର ଲୋକେସନ ଆକ୍ସେସକୁ ଆନୁମାନିକରୁ ସଠିକକୁ ପରିବର୍ତ୍ତନ କରିବେ?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ଏହି ଡିଭାଇସର ଆନୁମାନିକ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ର ଆନୁମାନିକ ଲୋକେସନକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ସଠିକ୍"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"(ଆନୁମାନିକ)"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ କ୍ୟାଲେଣ୍ଡର୍‌କୁ ଆକ୍ସେସ୍‍ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଆପଣଙ୍କର କେଲେଣ୍ଡରକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ SMS ମେସେଜ୍‍ ପଠାଇବା ଓ ଦେଖିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ SMS ମେସେଜ ପଠାଇବା ଏବଂ ଭ୍ୟୁ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କ ଡିଭାଇସରେ ଥିବା ଫଟୋ, ମିଡିଆ ଓ ଫାଇଲ୍‍ ଆକ୍ସେସ୍‍ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା ଫଟୋ, ମିଡିଆ ଏବଂ ଫାଇଲକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ଏହି ଡିଭାଇସରେ ଥିବା &lt;b&gt;ଫଟୋ, ଭିଡିଓ, ମ୍ୟୁଜିକ ଓ ଅଡିଓ&lt;/b&gt;କୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ଏହି ଡିଭାଇସରେ ଥିବା&lt;b&gt;ଫଟୋ, ଭିଡିଓ, ମ୍ୟୁଜିକ, ଅଡିଓ ଓ ଅନ୍ୟ ଫାଇଲ&lt;/b&gt; ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ଏହି ଡିଭାଇସରେ ଥିବା ମ୍ୟୁଜିକ ଏବଂ ଅଡିଓକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା ମ୍ୟୁଜିକ ଏବଂ ଅଡିଓକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ଏହି ଡିଭାଇସରେ ଥିବା ଫଟୋ ଏବଂ ଭିଡିଓଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା ଫଟୋ ଏବଂ ଭିଡିଓକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ଏହି ଡିଭାଇସରେ ଥିବା ଅଧିକ ଫଟୋ ଏବଂ ଭିଡିଓକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଥିବା ଅଧିକ ଫଟୋ ଏବଂ ଭିଡିଓକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଅଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁଥିବା ସମୟରେ କେବଳ ଏହା ଅଡିଓ ରେକର୍ଡ କରିବାକୁ ସକ୍ଷମ ହେବ"</string>
- <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଅଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହା ସବୁ ସମୟରେ ଅଡିଓ ରେକର୍ଡ କରିବାକୁ ଚାହିଁ ପାରେ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ ମାଇକ୍ରୋଫୋନର ଆକ୍ସେସ୍ ବଦଳାଇବେ କି?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ ମାଇକ୍ରୋଫୋନ ଆକ୍ସେସକୁ ପରିବର୍ତ୍ତନ କରିବେ?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହା ସବୁ ସମୟରେ ଅଡିଓ ରେକର୍ଡ କରିବାକୁ ଚାହେଁ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"ଆପଣ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଆପଣଙ୍କର ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପକୁ ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
- <string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଫଟୋ ଉଠାଇବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଆପଣଙ୍କର ଶାରୀରିକ କାର୍ଯ୍ୟକଳାପକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଫଟୋ ଉଠାଇବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଫଟୋ ଉଠାଇବା ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁଥିବା ସମୟରେ କେବଳ ଏହା ଛବି ନେବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ସକ୍ଷମ ହେବ"</string>
- <string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଛବି ନେବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
+ <string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଫଟୋ ଉଠାଇବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଫଟୋ ଉଠାଇବା ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହା ସବୁ ସମୟରେ ଛବି ନେବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଚାହିଁ ପାରେ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ କ୍ୟାମେରାର ଆକ୍ସେସ୍ ବଦଳାଇବେ କି?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ପାଇଁ କେମେରା ଆକ୍ସେସକୁ ପରିବର୍ତ୍ତନ କରିବେ?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ଆପଣ ଆପକୁ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ଏହା ସବୁ ସମୟରେ ଛବି ନେବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଚାହେଁ। "<annotation id="link">"ସେଟିଂସରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</annotation></string>
- <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_calllog" msgid="2065327180175371397">"ଆପଣଙ୍କ ଫୋନର କଲ ଲଗ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
+ <string name="permgrouprequest_device_aware_calllog" msgid="735079772627778095">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଆପଣଙ୍କର ଫୋନ କଲ ଲଗଗୁଡ଼ିକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &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_device_aware_phone" msgid="4389610977195521813">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଫୋନ କଲ କରିବା ଏବଂ ସେଗୁଡ଼ିକୁ ପରିଚାଳନା କରିବା ପାଇଁ &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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"&lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ମହତ୍ତ୍ୱପୂର୍ଣ୍ଣ ଲକ୍ଷଣ ବିଷୟରେ ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ଆପଣ ଆପ ବ୍ୟବହାର କରୁନଥିଲେ ମଧ୍ୟ, ବଡି ସେନ୍ସର ଡାଟାକୁ ସର୍ବଦା ଆକ୍ସେସ କରିବା ନିମନ୍ତେ ଏହି ଆପକୁ ଅନୁମତି ଦେବା ପାଇଁ, "<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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"ଆପକୁ ବ୍ୟବହାର କରାଯାଉଥିବା ବେଳେ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ବଡି ସେନ୍ସର ଡାଟାକୁ ଆକ୍ସେସ କରିବା ପାଇଁ &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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"ଆପଣଙ୍କ &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;ରେ ଆପଣଙ୍କୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ପଠାଇବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅନୁମତି ଦେବେ?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"ନିୟନ୍ତ୍ରିତ ଅନୁରୋଧଗୁଡ଼ିକ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
- <skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
- <skip />
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g>ର ଲୋକେସନ ଆକ୍ସେସ ଅଛି"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ କରିବା ପାଇଁ ଆପଣଙ୍କ ସଂସ୍ଥା <xliff:g id="APP_NAME">%1$s</xliff:g>କୁ ଅନୁମତି ଦିଏ"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"ଅନ୍ୟ ଅନୁମତିଗୁଡ଼ିକ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"ସିଷ୍ଟମ୍ ଦ୍ୱାରା ବ୍ୟବହୃତ ହୋଇଥିବା ଅନୁମତି"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"କେବଳ ସିଷ୍ଟମ୍ ଆପ୍ଲିକେସନଗୁଡ଼ିକ ଦ୍ୱାରା ବ୍ୟବହୃତ ହୋଇଥିବା ଅନୁମତିଗୁଡ଼ିକ।"</string>
<string name="additional_permissions_label" msgid="7693557637462569046">"ଅତିରିକ୍ତ ଅନୁମତି"</string>
<string name="additional_permissions_description" msgid="2186611950890732112">"ଆପ୍ଲିକେସନଗୁଡ଼ିକ ଦ୍ୱାରା ପରିଭାଷିତ ହୋଇଥିବା ଅନୁମତିଗୁଡ଼ିକ।"</string>
- <string name="privdash_label_camera" msgid="1426440033626198096">"କ୍ୟାମେରା"</string>
+ <string name="privdash_label_camera" msgid="1426440033626198096">"କେମେରା"</string>
<string name="privdash_label_microphone" msgid="8415035835803511693">"ମାଇକ୍ରୋଫୋନ"</string>
<string name="privdash_label_location" msgid="6882400763866489291">"ଲୋକେସନ"</string>
<string name="privdash_label_other" msgid="3710394147423236033">"ଅନ୍ୟ"</string>
@@ -537,7 +562,7 @@
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"ସ୍ଥିତି ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"ଆପଣଙ୍କ ଗୋପନୀୟତା ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"ଅଧିକ ସେଟିଂସ"</string>
- <string name="camera_toggle_label_qs" msgid="3880261453066157285">"କ୍ୟାମେରା ଆକ୍ସେସ"</string>
+ <string name="camera_toggle_label_qs" msgid="3880261453066157285">"କେମେରା ଆକ୍ସେସ"</string>
<string name="microphone_toggle_label_qs" msgid="8132912469813396552">"ମାଇକ ଆକ୍ସେସ"</string>
<string name="permissions_removed_qs" msgid="8957319130625294572">"ଅନୁମତିକୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"ବର୍ତ୍ତମାନର କ୍ୟାମେରା ବ୍ୟବହାର ଦେଖନ୍ତୁ"</string>
@@ -575,11 +600,11 @@
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"ପୃଷ୍ଠପଟ ଲୋକେସନ ଆକ୍ସେସ ଥିବା ଆପର ସମୀକ୍ଷା କରନ୍ତୁ"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> ଆପ ବନ୍ଦ ଥିବା ସମୟରେ ମଧ୍ୟ ସର୍ବଦା ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ କରିପାରିବ"</string>
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"ପୃଷ୍ଠପଟ ଲୋକେସନ ଆକ୍ସେସ ଥିବା ଆପର ସମୀକ୍ଷା କରନ୍ତୁ"</string>
- <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"ଏହି ଆପ ବନ୍ଦ ଥିବା ସମୟରେ ମଧ୍ୟ ସର୍ବଦା ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ କରିପାରିବ।\n\nକିଛି ସୁରକ୍ଷା ଏବଂ ଜରୁରୀକାଳୀନ ଆପ୍ସ ଆଶା କରାଯାଉଥିବା ଅନୁସାରେ କାର୍ଯ୍ୟ କରିବା ପାଇଁ ପୃଷ୍ଠପଟରେ ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ ଆବଶ୍ୟକ କରେ।"</string>
+ <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"ଏହି ଆପ ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ସର୍ବଦା ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ କରିପାରିବ।\n\nକିଛି ସୁରକ୍ଷା ଏବଂ ଜରୁରୀକାଳୀନ ଆପ୍ସ ଆଶା କରାଯାଉଥିବା ଅନୁସାରେ କାର୍ଯ୍ୟ କରିବା ପାଇଁ ପୃଷ୍ଠପଟରେ ଆପଣଙ୍କ ଲୋକେସନକୁ ଆକ୍ସେସ ଆବଶ୍ୟକ କରେ।"</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"ଆକ୍ସେସ ପରିବର୍ତ୍ତନ କରାଯାଇଛି"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"ବର୍ତ୍ତମାନର ଲୋକେସନ ବ୍ୟବହାର ଦେଖନ୍ତୁ"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"ଗୋପନୀୟତା ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
- <string name="camera_toggle_title" msgid="1251201397431837666">"କ୍ୟାମେରା ଆକ୍ସେସ"</string>
+ <string name="camera_toggle_title" msgid="1251201397431837666">"କେମେରା ଆକ୍ସେସ"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"ମାଇକ୍ରୋଫୋନ ଆକ୍ସେସ"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ"</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ। ଯଦି ଏହି ସେଟିଂ ବନ୍ଦ ଥାଏ, ତେବେ ଆପଣ ଏକ ଜରୁରୀକାଳୀନ ନମ୍ବରକୁ କଲ କରିବା ସମୟରେ ମାଇକ୍ରୋଫୋନ ଡାଟା ଏବେ ବି ସେୟାର କରାଯାଇପାରେ।"</string>
@@ -591,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ଏହି ଆପ ଉଲ୍ଲେଖ କରିଛି ଯେ ଏହା ତୃତୀୟ ପକ୍ଷଗୁଡ଼ିକ ସହ ଲୋକେସନ ଡାଟା ସେୟାର କରିପାରେ"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ଡାଟା ସେୟାରିଂ ଏବଂ ଲୋକେସନ"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ଡାଟା ସେୟାରିଂ ସୂଚନା କେଉଁଠାରୁ ଆସିଥାଏ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ଏହି ଆପ କିପରି ଡାଟା ସେୟାର କରେ ସେ ବିଷୟରେ ଡେଭେଲପର ଏହି ଡିଭାଇସର ନିର୍ମାତାଙ୍କୁ ସୂଚନା ପ୍ରଦାନ କରିଛନ୍ତି। ଡେଭେଲପର ସମୟ ଅନୁସାରେ ଏହି ସୂଚନାକୁ ଅପଡେଟ କରିପାରନ୍ତି।"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ଏହି ଆପ କିପରି ଡାଟା ସେୟାର କରେ ସେ ବିଷୟରେ ଡେଭେଲପର "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"ରେ ସୂଚନା ପ୍ରଦାନ କରିଛନ୍ତି। ଡେଭେଲପର ସମୟ ଅନୁସାରେ ଏହି ସୂଚନାକୁ ଅପଡେଟ କରିପାରନ୍ତି।"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ଏଥିପାଇଁ ଏହି ଆପ ଲୋକେସନ ଡାଟା ସେୟାର କରିପାରେ:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ଡାଟା ସେୟାରିଂ ଭିନ୍ନ ହୋଇଥାଏ"</string>
@@ -608,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ଡାଟା ସୁରକ୍ଷା"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ଲୋକେସନ ଡାଟା ସେୟାର କରାଯାଇପାରେ"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ଏହି ଆପ ଉଲ୍ଲେଖ କରିଛି ଯେ ଏହା ତୃତୀୟ ପକ୍ଷଗୁଡ଼ିକ ସହ ଆପଣଙ୍କ ଲୋକେସନ ଡାଟା ସେୟାର କରିପାରେ"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ଏହି ଲିଙ୍କ ଖୋଲାଯାଇପାରିବ ନାହିଁ"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ଲୋକେସନ ପାଇଁ ଡାଟା ସେୟାରିଂ ଅପଡେଟଗୁଡ଼ିକ"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ଆପଣଙ୍କ ଲୋକେସନ ଡାଟା ସେୟାର କରିବା ଉପାୟକୁ ପରିବର୍ତ୍ତନ କରିଥିବା ଆପ୍ସର ସମୀକ୍ଷା କରନ୍ତୁ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ଏହି ଆପ୍ସ ଆପଣଙ୍କ ଲୋକେସନ ଡାଟା ସେୟାର କରିବା ଉପାୟକୁ ପରିବର୍ତ୍ତନ କରିଛି। ସେଗୁଡ଼ିକ ଏହାକୁ ପୂର୍ବରୁ ସେୟାର କରିନଥାଇପାରେ କିମ୍ବା ବର୍ତ୍ତମାନ ଏହାକୁ ବିଜ୍ଞାପନ ବା ମାର୍କେଟିଂ ଉଦ୍ଦେଶ୍ୟରେ ସେୟାର କରିପାରେ।"</string>
diff --git a/PermissionController/res/values-pa-v33/strings.xml b/PermissionController/res/values-pa-v33/strings.xml
index 19930a93b..03e18ae50 100644
--- a/PermissionController/res/values-pa-v33/strings.xml
+++ b/PermissionController/res/values-pa-v33/strings.xml
@@ -27,11 +27,10 @@
<string name="safety_center_entry_group_with_actions_needed_content_description" msgid="2708884606775932657">"ਸੂਚੀ। <xliff:g id="ENTRY_TITLE">%1$s</xliff:g>. ਕਾਰਵਾਈਆਂ ਦੀ ਲੋੜ ਹੈ। <xliff:g id="ENTRY_SUMMARY">%2$s</xliff:g>"</string>
<string name="safety_center_entry_group_item_content_description" msgid="7348298582877249787">"ਸੂਚੀ ਆਈਟਮ। <xliff:g id="ENTRY_ITEM_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_ITEM_SUMMARY">%2$s</xliff:g>"</string>
<string name="safety_center_entry_content_description" msgid="3639565652938224321">"<xliff:g id="ENTRY_ITEM_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_ITEM_SUMMARY">%2$s</xliff:g>"</string>
- <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ਹੋਰ ਸੁਚੇਤਨਾਵਾਂ"</string>
+ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"ਹੋਰ ਅਲਰਟ"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ਖਾਰਜ ਕੀਤੀਆਂ ਗਈਆਂ ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ ਇੱਕ ਹੋਰ ਸੁਚੇਤਨਾ ਦੇਖੋ}one{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ # ਹੋਰ ਸੁਚੇਤਨਾ ਦੇਖੋ}other{ਵਿਸਤਾਰ ਕਰੋ ਅਤੇ # ਹੋਰ ਸੁਚੇਤਨਾਵਾਂ ਦੇਖੋ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ਸੁਚੇਤਨਾ। <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ਕਾਰਵਾਈ ਪੂਰੀ ਹੋਈ"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ਉਨ੍ਹਾਂ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕਰੋ ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਵਿੱਚ ਸੁਰੱਖਿਆ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"ਸੁਰੱਖਿਆ ਅਤੇ ਪਰਦੇਦਾਰੀ ਸੰਬੰਧੀ ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ"</string>
diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml
index 055596f04..83929d9ea 100644
--- a/PermissionController/res/values-pa/strings.xml
+++ b/PermissionController/res/values-pa/strings.xml
@@ -27,12 +27,12 @@
<string name="off" msgid="1438489226422866263">"ਬੰਦ"</string>
<string name="uninstall_or_disable" msgid="4496612999740858933">"ਅਣਸਥਾਪਤ ਕਰੋ ਜਾਂ ਬੰਦ ਕਰੋ"</string>
<string name="app_not_found_dlg_title" msgid="6029482906093859756">"ਐਪ ਨਹੀਂ ਮਿਲੀ"</string>
- <string name="grant_dialog_button_deny" msgid="88262611492697192">"ਨਾ ਕਰਨ ਦਿਓ"</string>
+ <string name="grant_dialog_button_deny" msgid="88262611492697192">"ਆਗਿਆ ਨਾ ਦਿਓ"</string>
<string name="grant_dialog_button_deny_and_dont_ask_again" msgid="1748925431574312595">"ਆਗਿਆ ਨਾ ਦਿਓ ਅਤੇ ਦੁਬਾਰਾ ਨਾ ਪੁੱਛੋ"</string>
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"“ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਹੋਣ ਵੇਲੇ” ਨੂੰ ਰੱਖੋ"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“ਸਿਰਫ਼ ਇਸ ਸਮੇਂ ਲਈ ਇਜਾਜ਼ਤ ਦਿਓ” ਰੱਖੋ"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"ਹੋਰ ਜਾਣਕਾਰੀ"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"ਸਭ ਨੂੰ ਆਗਿਆ ਦਿਓ"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"ਸਭ \'ਤੇ ਕਰਨ ਦਿਓ"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"ਹਮੇਸ਼ਾਂ ਸਭ ਨੂੰ ਆਗਿਆ ਦਿਓ"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਚੁਣੋ"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"ਹੋਰ ਚੁਣੋ"</string>
@@ -195,7 +195,7 @@
<string name="approximate_image_description" msgid="938803699637069884">"ਅੰਦਾਜ਼ਨ ਟਿਕਾਣਾ"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"ਸਹੀ ਟਿਕਾਣਾ ਵਰਤੋ"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"ਜਦੋਂ ਸਹੀ ਟਿਕਾਣੇ ਦੀ ਜਾਣਕਾਰੀ ਬੰਦ ਹੋਵੇ, ਤਾਂ ਐਪਾਂ ਤੁਹਾਡੀ ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ ਦੀ ਜਾਣਕਾਰੀ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
- <string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> ਇਜਾਜ਼ਤ"</string>
+ <string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g> ਸੰਬੰਧੀ ਇਜਾਜ਼ਤ"</string>
<string name="app_permission_header" msgid="2951363137032603806">"ਇਸ ਐਪ ਲਈ <xliff:g id="PERM">%1$s</xliff:g> ਪਹੁੰਚ"</string>
<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>
@@ -221,12 +221,12 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"ਅਣਵਰਤੀਆਂ ਐਪਾਂ"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"ਜੇ ਕਿਸੇ ਐਪ ਨੂੰ ਕੁਝ ਮਹੀਨਿਆਂ ਤੱਕ ਵਰਤਿਆ ਨਹੀਂ ਜਾਂਦਾ ਹੈ, ਤਾਂ:\n\n• ਤੁਹਾਡੇ ਡਾਟੇ ਦੀ ਸੁਰੱਖਿਆ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ\n• ਬੈਟਰੀ ਬਚਾਉਣ ਲਈ ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰ ਦਿੱਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ\n• ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਅਸਥਾਈ ਫ਼ਾਈਲਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ\n\nਦੁਬਾਰਾ ਇਜਾਜ਼ਤਾਂ ਦੇਣ ਅਤੇ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਐਪ ਖੋਲ੍ਹੋ।"</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"ਜੇ ਕਿਸੇ ਐਪ ਨੂੰ ਇੱਕ ਮਹੀਨੇ ਤੱਕ ਨਹੀਂ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ:\n\n• ਤੁਹਾਡੇ ਡਾਟੇ ਦੀ ਸੁਰੱਖਿਆ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ\n• ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਅਸਥਾਈ ਫ਼ਾਈਲਾਂ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ\n\nਇਜਾਜ਼ਤਾਂ ਦੀ ਦੁਬਾਰਾ ਆਗਿਆ ਦੇਣ ਲਈ, ਐਪ ਨੂੰ ਖੋਲ੍ਹੋ।"</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨੇ ਤੋਂ ਵੱਧ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}one{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨੇ ਤੋਂ ਵੱਧ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}other{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨਿਆਂ ਤੋਂ ਵੱਧ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨੇ ਤੋਂ ਵੱਧ ਸਮਾਂ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}one{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨੇ ਤੋਂ ਵੱਧ ਸਮਾਂ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}other{ਪਿਛਲੀ ਵਾਰ # ਮਹੀਨਿਆਂ ਤੋਂ ਵੱਧ ਸਮਾਂ ਪਹਿਲਾਂ ਖੋਲ੍ਹੀਆਂ ਗਈਆਂ}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"ਐਪ ਨੂੰ ਆਖਰੀ ਵਾਰ <xliff:g id="DATE">%s</xliff:g> ਨੂੰ ਖੋਲ੍ਹਿਆ ਗਿਆ"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"ਆਖਰੀ ਵਾਰ <xliff:g id="DATE">%s</xliff:g> ਨੂੰ ਖੋਲ੍ਹਿਆ ਗਿਆ"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"ਜੇ ਤੁਸੀਂ ਸਾਰੀਆਂ ਫ਼ਾਈਲਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਇਹ ਐਪ ਇਸ ਡੀਵਾਈਸ ਜਾਂ ਕਨੈਕਟ ਕੀਤੇ ਸਟੋਰੇਜ ਡੀਵਾਈਸਾਂ ਦੀ ਸਾਂਝੀ ਸਟੋਰੇਜ ਵਿੱਚ ਕਿਸੇ ਵੀ ਫ਼ਾਈਲ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ, ਉਸ ਵਿੱਚ ਸੋਧ ਕਰ ਸਕਦੀ ਅਤੇ ਉਸ ਨੂੰ ਮਿਟਾ ਸਕਦੀ ਹੈ। ਐਪ ਤੁਹਾਨੂੰ ਪੁੱਛੇ ਬਿਨਾਂ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"ਕੀ ਇਸ ਐਪ ਨੂੰ ਇਸ ਡੀਵਾਈਸ ਜਾਂ ਕਨੈਕਟ ਕੀਤੇ ਸਟੋਰੇਜ ਡੀਵਾਈਸਾਂ \'ਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ, ਉਹਨਾਂ ਨੂੰ ਸੋਧਣ ਅਤੇ ਮਿਟਾਉਣ ਦੇਣਾ ਹੈ? ਇਹ ਐਪ ਤੁਹਾਨੂੰ ਪੁੱਛੇ ਬਿਨਾਂ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਐਪਾਂ <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਐਪਾਂ ਇਹ ਕਰ ਸਕਦੀਆਂ ਹਨ: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਐਪਾਂ ਤੁਹਾਡੀ ਸਰੀਰਕ ਸਰਗਰਮੀ, ਜਿਵੇਂ ਕਿ ਪੈਦਲ-ਸੈਰ, ਸਾਈਕਲ ਚਲਾਉਣਾ, ਗੱਡੀ ਚਲਾਉਣਾ, ਕਦਮਾਂ ਦੀ ਗਿਣਤੀ ਅਤੇ ਹੋਰ ਚੀਜ਼ਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"ਇਸ ਇਜਾਜ਼ਤ ਵਾਲੀਆਂ ਐਪਾਂ ਫ਼ੋਨ ਕਾਲ ਲੌਗ ਪੜ੍ਹ-ਲਿਖ ਸਕਦੀਆਂ ਹਨ"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"ਸਹਾਇਕ ਟ੍ਰਿਗਰ ਦੀ ਸੂਹ ਦਿਖਾਓ"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"ਜਦੋਂ ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਕਰਨ ਲਈ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ ਤਾਂ ਸਥਿਤੀ ਪੱਟੀ ਵਿੱਚ ਪ੍ਰਤੀਕ ਦਿਖਾਓ"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ ਅਤੇ ਮੀਡੀਆ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਹੀ ਐਪ ਕੋਲ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇਗੀ"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ਸ਼ਾਇਦ ਇਸ ਐਪ ਨੂੰ ਹਰ ਵੇਲੇ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਹੋਵੇ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਨਾ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਗਿਆ ਦਿਓ।"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਲਈ ਟਿਕਾਣਾ ਪਹੁੰਚ ਨੂੰ ਬਦਲਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"ਇਸ ਐਪ ਨੂੰ ਹਰ ਵੇਲੇ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਚਾਹੀਦੀ ਹੈ, ਭਾਵੇਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਨਾ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਗਿਆ ਦਿਓ।"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਲੱਭਣ, ਉਨ੍ਹਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੇਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਨਜ਼ਦੀਕੀ ਡੀਵਾਈਸਾਂ ਲੱਭਣ, ਉਨ੍ਹਾਂ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਅਤੇ ਸੰਬੰਧਿਤ ਸਥਿਤੀ ਨੂੰ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੇਣਾ ਹੈ? "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਆਗਿਆ ਦਿਓ।"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"ਕੀ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ਦੀ ਟਿਕਾਣਾ ਪਹੁੰਚ ਨੂੰ ਅੰਦਾਜ਼ਨ ਤੋਂ ਸਹੀ ਟਿਕਾਣੇ \'ਤੇ ਬਦਲਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ ਦੇ ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ਸਹੀ"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ਅੰਦਾਜ਼ਨ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨੀ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ SMS ਸੁਨੇਹੇ ਭੇਜਣ ਅਤੇ ਦੇਖਣ ਦੇਣੇ ਹਨ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ \'ਤੇ &lt;b&gt;ਫ਼ੋਟੋਆਂ, ਵੀਡੀਓ, ਸੰਗੀਤ ਅਤੇ ਆਡੀਓ&lt;/b&gt; ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ \'ਤੇ &lt;b&gt;ਫ਼ੋਟੋਆਂ, ਵੀਡੀਓ, ਸੰਗੀਤ, ਆਡੀਓ ਅਤੇ ਹੋਰ ਫ਼ਾਈਲਾਂ&lt;/b&gt; ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸੰਗੀਤ ਅਤੇ ਆਡੀਓ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਹੋਰ ਫ਼ੋਟੋਆਂ ਅਤੇ ਵੀਡੀਓ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਹੀ ਐਪ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕੇਗੀ"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ਇਹ ਐਪ ਹਰ ਵੇਲੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਸਕਦੀ ਹੈ, ਉਦੋਂ ਵੀ ਜਦੋਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰ ਰਹੇ ਹੋਵੋ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਜਾਜ਼ਤ ਦਿਓ।"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਲਈ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਪਹੁੰਚ ਨੂੰ ਬਦਲਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"ਇਹ ਐਪ ਹਰ ਵੇਲੇ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗਦੀ ਹੈ, ਉਦੋਂ ਵੀ ਜਦੋਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰ ਰਹੇ ਹੋਵੋ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਜਾਜ਼ਤ ਦਿਓ।"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਪਣੀ ਸਰੀਰਕ ਸਰਗਰਮੀ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤਸਵੀਰਾਂ ਖਿੱਚਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੇਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰਨ ਵੇਲੇ ਹੀ ਐਪ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕੇਗੀ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰ ਸਕੇਗੀ"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤਸਵੀਰਾਂ ਖਿੱਚਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ਇਹ ਐਪ ਹਰ ਵੇਲੇ ਤਸਵੀਰਾਂ ਖਿੱਚਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗ ਸਕਦੀ ਹੈ, ਉਦੋਂ ਵੀ ਜਦੋਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰ ਰਹੇ ਹੋਵੋ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਜਾਜ਼ਤ ਦਿਓ।"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਲਈ ਕੈਮਰਾ ਪਹੁੰਚ ਨੂੰ ਬਦਲਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"ਇਹ ਐਪ ਹਰ ਵੇਲੇ ਤਸਵੀਰਾਂ ਖਿੱਚਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਮੰਗਦੀ ਹੈ, ਉਦੋਂ ਵੀ ਜਦੋਂ ਤੁਸੀਂ ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰ ਰਹੇ ਹੋਵੋ। "<annotation id="link">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਇਜਾਜ਼ਤ ਦਿਓ।"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੇ ਕਾਲ ਲੌਗਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੇਣਾ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਡੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਲੱਛਣਾਂ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ਐਪ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰਨ ਵੇਲੇ ਵੀ, ਇਸ ਐਪ ਨੂੰ ਹਰ ਸਮੇਂ ਸਰੀਰ ਸੰਬੰਧੀ ਸੈਂਸਰ ਡਾਟੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣ ਲਈ, "<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="auto_granted_permissions" msgid="6009452264824455892">"ਨਿਯੰਤਰਿਤ ਇਜਾਜ਼ਤਾਂ"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤੁਹਾਨੂੰ ਸੂਚਨਾਵਾਂ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"ਨਿਯੰਤਰਿਤ ਇਜਾਜ਼ਤਾਂ"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਦੀ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਹੈ"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ਤੁਹਾਡੀ ਸੰਸਥਾ <xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"ਹੋਰ ਇਜਾਜ਼ਤਾਂ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"ਸਿਸਟਮ ਵੱਲੋਂ ਵਰਤੀ ਗਈ ਇਜਾਜ਼ਤ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"ਸਿਰਫ਼ ਸਿਸਟਮ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਵਰਤੀਆਂ ਗਈਆਂ ਇਜਾਜ਼ਤਾਂ"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ਇਸ ਐਪ ਨੇ ਸਪਸ਼ਟ ਕੀਤਾ ਕਿ ਇਹ ਤੀਜੀਆਂ ਧਿਰਾਂ ਨਾਲ ਟਿਕਾਣੇ ਦੇ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਕਰ ਸਕਦੀ ਹੈ"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਅਤੇ ਟਿਕਾਣਾ"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਜਾਣਕਾਰੀ ਕਿੱਥੋਂ ਆਉਂਦੀ ਹੈ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ਵਿਕਾਸਕਾਰ ਨੇ ਇਸ ਐਪ ਵੱਲੋਂ ਡਾਟਾ ਸਾਂਝਾ ਕੀਤੇ ਜਾਣ ਦੇ ਤਰੀਕੇ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਮਾਤਾ ਨੂੰ ਮੁਹੱਈਆ ਕਰਵਾਈ ਹੈ। ਵਿਕਾਸਕਾਰ ਸਮੇਂ-ਸਮੇਂ \'ਤੇ ਇਸ ਜਾਣਕਾਰੀ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ਵਿਕਾਸਕਾਰ ਨੇ ਇਸ ਐਪ ਵੱਲੋਂ ਡਾਟਾ ਸਾਂਝਾ ਕੀਤੇ ਜਾਣ ਦੇ ਤਰੀਕੇ ਬਾਰੇ ਜਾਣਕਾਰੀ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" ਨੂੰ ਮੁਹੱਈਆ ਕਰਵਾਈ ਹੈ। ਵਿਕਾਸਕਾਰ ਸਮੇਂ-ਸਮੇਂ \'ਤੇ ਇਸ ਜਾਣਕਾਰੀ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ਇਹ ਐਪ ਇਸ ਲਈ ਟਿਕਾਣੇ ਦਾ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀ ਹੈ:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਵੱਖ-ਵੱਖ ਹੁੰਦਾ ਹੈ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ਡਾਟਾ ਸੁਰੱਖਿਆ"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ਟਿਕਾਣੇ ਦਾ ਡਾਟਾ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ਇਸ ਐਪ ਨੇ ਸਪਸ਼ਟ ਕੀਤਾ ਕਿ ਇਹ ਤੀਜੀਆਂ ਧਿਰਾਂ ਨਾਲ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਦੇ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਕਰ ਸਕਦੀ ਹੈ"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ਇਸ ਲਿੰਕ ਨੂੰ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ਟਿਕਾਣੇ ਲਈ ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਅੱਪਡੇਟ"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ਉਨ੍ਹਾਂ ਐਪਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ ਜਿਨ੍ਹਾਂ ਨੇ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਦੇ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤੇ ਜਾਣ ਦਾ ਤਰੀਕਾ ਬਦਲ ਦਿੱਤਾ ਹੈ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ਇਨ੍ਹਾਂ ਐਪਾਂ ਨੇ ਉਨ੍ਹਾਂ ਵੱਲੋਂ ਤੁਹਾਡੇ ਟਿਕਾਣੇ ਦੇ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤੇ ਜਾਣ ਦਾ ਤਰੀਕਾ ਬਦਲ ਦਿੱਤਾ ਹੈ। ਉਨ੍ਹਾਂ ਨੇ ਸ਼ਾਇਦ ਇਸਨੂੰ ਪਹਿਲਾਂ ਸਾਂਝਾ ਨਾ ਕੀਤਾ ਹੋਵੇ, ਜਾਂ ਉਹ ਸ਼ਾਇਦ ਹੁਣ ਵਿਗਿਆਪਨ ਜਾਂ ਮਾਰਕੀਟਿੰਗ ਸੰਬੰਧੀ ਉਦੇਸ਼ਾਂ ਲਈ ਹੁਣ ਇਸਨੂੰ ਸਾਂਝਾ ਕਰਨ।"</string>
diff --git a/PermissionController/res/values-pl-v33/strings.xml b/PermissionController/res/values-pl-v33/strings.xml
index dbead75d7..a6cdbd775 100644
--- a/PermissionController/res/values-pl-v33/strings.xml
+++ b/PermissionController/res/values-pl-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Więcej alertów"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Odrzucone alerty"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Rozwiń i zobacz jeszcze 1 alert}few{Rozwiń i zobacz jeszcze # alerty}many{Rozwiń i zobacz jeszcze # alertów}other{Rozwiń i zobacz jeszcze # alertu}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alert. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Działanie ukończone"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Sprawdź ustawienia, które mogą zwiększyć bezpieczeństwo Twojego urządzenia"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Szybkie ustawienia bezpieczeństwa i prywatności"</string>
diff --git a/PermissionController/res/values-pl-v34/strings.xml b/PermissionController/res/values-pl-v34/strings.xml
index 1df9c79b1..b69bf4c4f 100644
--- a/PermissionController/res/values-pl-v34/strings.xml
+++ b/PermissionController/res/values-pl-v34/strings.xml
@@ -22,6 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"Zarządzaj dostępem aplikacji do danych dotyczących zdrowia"</string>
<string name="location_settings" msgid="8863940440881290182">"Dostęp do lokalizacji"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Aplikacje i usługi. Jeśli wyłączysz to ustawienie, dane mikrofonu wciąż mogą być udostępniane podczas połączenia z numerem alarmowym"</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"Aplikacje i usługi"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Dotyczy aplikacji i usług. Jeśli wyłączysz to ustawienie, dane mikrofonu wciąż mogą być udostępniane podczas połączenia z numerem alarmowym"</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"Dotyczy aplikacji i usług"</string>
</resources>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index be36e5f7e..d470c9e5f 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"I tak nie zezwalaj"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Odrzuć"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> z <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Zawsze zezwalać aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na to działanie: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Zawsze zezwalać aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na to działanie: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Tylko przy używaniu aplikacji"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Zawsze"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Nie zezwalaj i nie pytaj ponownie"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Ostatnio otwarto <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Jeśli pozwolisz zarządzać wszystkimi plikami, ta aplikacja będzie mogła odczytywać, modyfikować i usuwać dowolne pliki na tym urządzeniu lub zewnętrznych urządzeniach do przechowywania danych. Ta aplikacja może bez pytania uzyskiwać dostęp do plików."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Zezwól tej aplikacji na odczytywanie, modyfikowanie i usuwanie plików na tym urządzeniu oraz wszelkich podłączonych zewnętrznych urządzeniach do przechowywania danych. Ta aplikacja może bez pytania uzyskiwać dostęp do plików."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacje z tym uprawnieniem mogą <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacje z tym uprawnieniem mogą wykonać to działanie: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Aplikacje z tym uprawnieniem mają dostęp do danych o Twojej aktywności fizycznej takiej jak spacery, jazda na rowerze, jazda samochodem, liczba kroków i inne"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Aplikacje z tym uprawnieniem mają dostęp do kalendarza"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Aplikacje z tym uprawnieniem mogą odczytywać i zapisywać rejestr połączeń telefonicznych"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Pokaż wykrywanie wyzwalacza asystenta"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Pokaż ikonę na pasku stanu, gdy używany jest mikrofon do uruchomienia asystenta głosowego"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć i multimediów na urządzeniu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do kontaktów?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do lokalizacji urządzenia?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacja będzie mieć dostęp do lokalizacji tylko wtedy, gdy będzie używana"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do lokalizacji urządzenia?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Aplikacja chce mieć stały dostęp do Twojej lokalizacji, nawet gdy nie jest używana. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Zmienić uprawnienia dostępu do lokalizacji w przypadku aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>”?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplikacja chce mieć stały dostęp do Twojej lokalizacji, nawet gdy nie jest używana. "<annotation id="link">"Zezwól w ustawieniach"</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie lokalizacji tego urządzenia?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie lokalizacji tego urządzenia? "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie względnego położenia urządzeń w pobliżu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na znalezienie, połączenie i ustalenie względnego położenia urządzeń w pobliżu? "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Zmienić dostęp aplikacji <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> do lokalizacji przybliżonej na dostęp do lokalizacji dokładnej?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Zezwolić aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>” na dostęp do przybliżonej lokalizacji urządzenia?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Dokładna"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Przybliżona"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do kalendarza?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na wysyłanie i wyświetlanie SMS-ów?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć, multimediów i plików na urządzeniu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć, filmów, muzyki i dźwięków na tym urządzeniu?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć, filmów, muzyki, dźwięków i innych plików na tym urządzeniu?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do muzyki i innych plików audio na tym urządzeniu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do zdjęć i filmów na tym urządzeniu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do kolejnych zdjęć i filmów na tym urządzeniu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na nagrywanie dźwięku?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacja będzie mogła nagrywać dźwięk tylko wtedy, gdy będzie używana"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Zezwolić aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>” na nagrywanie dźwięku?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ta aplikacja chce móc nagrywać dźwięk przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Zmienić uprawnienia dostępu do mikrofonu w przypadku aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>”?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ta aplikacja chce móc nagrywać dźwięk przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na dostęp do aktywności fizycznej?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na robienie zdjęć i nagrywanie filmów?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacja będzie mogła robić zdjęcia i nagrywać filmy tylko wtedy, gdy będzie używana"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Zezwolić aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>” na robienie zdjęć i nagrywanie filmów?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ta aplikacja chce móc robić zdjęcia i nagrywać filmy przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Zmienić uprawnienia dostępu do aparatu w przypadku aplikacji „<xliff:g id="APP_NAME">%1$s</xliff:g>”?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ta aplikacja chce móc robić zdjęcia i nagrywać filmy przez cały czas, nawet gdy jej nie używasz. "<annotation id="link">"Zezwól w ustawieniach."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Pozwolenia kontrolowane"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Pozwolenia kontrolowane"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> ma dostęp do lokalizacji"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organizacja zezwala na dostęp aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> do Twojej lokalizacji"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Inne uprawnienia"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Uprawnienia używane przez system"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Uprawnienia używane tylko przez aplikacje systemowe."</string>
@@ -572,17 +624,17 @@
<string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Ta aplikacja nie obsługuje najnowszej wersji Androida. Jeśli ta aplikacja nie ma dostępu do muzyki i plików audio, nie będzie również miała dostępu do zdjęć i filmów."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Ta aplikacja nie obsługuje najnowszej wersji Androida. Jeśli ta aplikacja ma dostęp do zdjęć i filmów, będzie również miała dostęp do muzyki i plików audio."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Ta aplikacja nie obsługuje najnowszej wersji Androida. Jeśli ta aplikacja nie ma dostępu do muzyki i plików audio, nie będzie również miała dostępu do zdjęć i filmów."</string>
- <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Zweryfikuj aplikację z dostępem do lokalizacji w tle"</string>
+ <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Zweryfikuj aplikację z dostępem w tle do lokalizacji"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"Aplikacja <xliff:g id="APP_NAME">%s</xliff:g> ma dostęp do Twojej lokalizacji, nawet kiedy jest zamknięta"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Zweryfikuj aplikację z dostępem do lokalizacji w tle"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Zweryfikuj aplikację z dostępem w tle do lokalizacji"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Ta aplikacja ma dostęp do Twojej lokalizacji nawet wtedy, kiedy jest zamknięta.\n\nNiektóre aplikacje z dziedziny bezpieczeństwa i alarmowe wymagają dostępu w tle do lokalizacji, aby mogły działać zgodnie z oczekiwaniami."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Uprawnienia dostępu zostały zmienione"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Zobacz ostatnie użycie lokalizacji"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Ustawienia prywatności"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Dostęp do aparatu"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Dostęp do mikrofonu"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Aplikacje i usługi"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"Aplikacje i usługi. Jeśli wyłączysz to ustawienie, dane mikrofonu wciąż mogą być udostępniane podczas połączenia z numerem alarmowym."</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Dotyczy aplikacji i usług"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"Dotyczy aplikacji i usług. Jeśli wyłączysz to ustawienie, dane mikrofonu wciąż mogą być udostępniane podczas połączenia z numerem alarmowym."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Wyświetl aplikacje i usługi z dostępem do lokalizacji"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Pokazuj dostęp do schowka"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Pokazuj komunikat, gdy aplikacja uzyskuje dostęp do skopiowanego tekstu, obrazów lub innych treści"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ta aplikacja deklaruje, że może udostępniać dane o lokalizacji osobom trzecim"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Udostępnianie danych i lokalizacja"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Źródło informacji o udostępnianiu danych"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Deweloper przekazał producentowi urządzenia informacje o tym, jak aplikacja udostępnia dane. Informacje mogą być aktualizowane."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Deweloper zamieścił informacje o tym, jak aplikacja udostępnia dane, w: "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Informacje mogą być aktualizowane."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Możliwe cele udostępniania danych o lokalizacji:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Różnice w udostępnianiu danych"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Bezpieczeństwo danych"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Dane o lokalizacji mogą być udostępniane"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ta aplikacja deklaruje, że może udostępniać Twoje dane o lokalizacji innym podmiotom"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Nie można otworzyć tego linku"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Zmiany w udostępnianiu danych o lokalizacji"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Przejrzyj aplikacje, które zmieniły sposób udostępniania Twoich danych o lokalizacji"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Te aplikacje zmieniły sposób udostępniania Twoich danych o lokalizacji. Wcześniej mogły ich nie udostępniać lub teraz zaczęły je udostępniać w celach marketingowych."</string>
diff --git a/PermissionController/res/values-pt-rBR-v33/strings.xml b/PermissionController/res/values-pt-rBR-v33/strings.xml
index 01a8edce9..aeda06c8f 100644
--- a/PermissionController/res/values-pt-rBR-v33/strings.xml
+++ b/PermissionController/res/values-pt-rBR-v33/strings.xml
@@ -40,7 +40,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Chave. <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g>. <xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Alternar"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Abrir"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Revisar configura&amp;#173;ções"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Revisar configura­ções"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Configurações"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Informações"</string>
</resources>
diff --git a/PermissionController/res/values-pt-rBR/strings.xml b/PermissionController/res/values-pt-rBR/strings.xml
index f0a018192..5a51eb1d5 100644
--- a/PermissionController/res/values-pt-rBR/strings.xml
+++ b/PermissionController/res/values-pt-rBR/strings.xml
@@ -34,14 +34,14 @@
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Mais inform."</string>
<string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Permitir tudo"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Sempre permitir tudo"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Alguns vídeos e fotos"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Selecionar fotos e vídeos"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Selecionar mais"</string>
<string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Não selecionar mais"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Não permitir mesmo assim"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Dispensar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Sempre permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Permitir o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Sempre permitir o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Apenas ao usar o app"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Sempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Não permitir e não perguntar de novo"</string>
@@ -198,7 +198,7 @@
<string name="app_permission_title" msgid="2090897901051370711">"Permissão para acessar <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Permitir que este app acesse: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<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="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar 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>
@@ -369,7 +369,7 @@
<string name="role_sms_search_keywords" msgid="8022048144395047352">"mensagem de texto, enviar mensagens de texto, mensagens"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"App padrão de emergência"</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"App de emergência"</string>
- <string name="role_emergency_description" msgid="5051840234887686630">"Apps que permitem registrar informações médicas e disponibilizá-las para socorristas, receber alertas sobre eventos climáticos graves e desastres e notificar outras pessoas se você precisar de ajuda"</string>
+ <string name="role_emergency_description" msgid="5051840234887686630">"Apps que permitem registrar informações de saúde e disponibilizá-las para socorristas, receber alertas sobre eventos climáticos graves e desastres e notificar outras pessoas se você precisar de ajuda"</string>
<string name="role_emergency_request_title" msgid="8469579020654348567">"Definir <xliff:g id="APP_NAME">%1$s</xliff:g> como app padrão de emergência?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"Nenhuma permissão necessária"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"em emergências"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostrar detecção de gatilho do assistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostrar ícone na barra de status quando o microfone for usado para ativar o assistente por voz"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos e mídia no seu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse seus contatos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse a localização deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"O app só terá acesso ao local enquanto estiver sendo usado"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse a localização deste dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Este app pode querer acessar sua localização o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita o acesso nas configurações"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Mudar o acesso que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem à localização?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Este app quer acessar sua localização o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita o acesso nas configurações"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, conecte-se e determine a posição relativa de dispositivos por perto?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, conecte-se e determine a posição relativa de dispositivos por perto? "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Permitir a troca para que o app <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> acesse o local exato (em vez do aproximado)?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse o local aproximado deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exata"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse sua agenda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse e envie mensagens SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos, mídia e arquivos no seu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse &lt;b&gt;fotos, vídeos, músicas e áudios&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse &lt;b&gt;fotos, vídeos, músicas, áudios e outros arquivos&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse músicas e áudios neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse mais fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"O app poderá gravar áudio apenas quando estiver em uso"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Este app pode querer gravar áudio a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Mudar o acesso que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem ao microfone?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Este app quer gravar áudio a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse sua atividade física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"O app poderá tirar fotos e gravar vídeos apenas quando estiver em uso"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Este app pode querer tirar fotos e gravar vídeos a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Mudar o acesso que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem à câmera?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Este app quer tirar fotos e gravar vídeos a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permissões controladas"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> tem acesso à localização"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Sua organização permite que o app <xliff:g id="APP_NAME">%1$s</xliff:g> tenha acesso à sua localização"</string>
@@ -508,7 +562,7 @@
<string name="privdash_label_camera" msgid="1426440033626198096">"Câmera"</string>
<string name="privdash_label_microphone" msgid="8415035835803511693">"Microfone"</string>
<string name="privdash_label_location" msgid="6882400763866489291">"Localização"</string>
- <string name="privdash_label_other" msgid="3710394147423236033">"Outra"</string>
+ <string name="privdash_label_other" msgid="3710394147423236033">"Outras"</string>
<string name="privdash_label_none" msgid="5991866260360484858">"Nenhuma"</string>
<string name="privdash_label_24h" msgid="1512532123865375319">"Últimas\n24 horas"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Nos últimos\nsete dias"</string>
@@ -532,7 +586,7 @@
<string name="security_settings" msgid="3808106921175271317">"Configurações de segurança"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Permissões"</string>
<string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Segurança e privacidade"</string>
- <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Ver status"</string>
+ <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Checar status"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Seus controles de privacidade"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Mais configurações"</string>
<string name="camera_toggle_label_qs" msgid="3880261453066157285">"Acesso à câmera"</string>
@@ -547,7 +601,7 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"Usada recentemente por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"Uso recente por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"Usada recentemente por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -575,7 +629,7 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Revisar apps com acesso à localização em segundo plano"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Este app sempre pode acessar sua localização, mesmo quando está fechado.\n\nAlguns apps de segurança e emergência exigem acesso à sua localização em segundo plano para funcionar corretamente."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"O acesso foi mudado"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Ver o uso recente da localização"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Verificar o uso recente da localização"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Controles de privacidade"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Acesso à câmera"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Acesso ao microfone"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Este app declarou que pode compartilhar dados de local com terceiros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Local e compartilhamento de dados"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De onde vêm as informações do compartilhamento de dados"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"O desenvolvedor forneceu informações para o fabricante do dispositivo sobre como este app compartilha dados. O desenvolvedor pode atualizar essas informações com o tempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"O desenvolvedor forneceu informações para "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre como esse app compartilha dados. O desenvolvedor pode atualizar essas informações com o tempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Esse app pode compartilhar dados de local para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"O compartilhamento de dados varia"</string>
@@ -606,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Segurança dos dados"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Os dados de local podem ser compartilhados"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Este app indicou que pode compartilhar seus dados de local com terceiros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Não é possível abrir esse link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Atualizações no compartilhamento de dados de local"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"Revise os apps que mudaram a forma de compartilhar os dados de local"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"Conferir apps que mudaram a forma de compartilhar dados de local"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Esses apps mudaram a forma de compartilhar os dados de local. É possível que eles não tenham compartilhado antes ou que agora compartilhem para fins de publicidade ou marketing."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Os desenvolvedores desses apps oferecem informações sobre as práticas deles de compartilhamento de dados com uma app store. Eles podem atualizar essas informações com o tempo.\n\nAs práticas de compartilhamento de dados podem variar de acordo com a versão do app e com a idade, o uso e a região do usuário."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Saiba mais sobre o compartilhamento de dados"</string>
diff --git a/PermissionController/res/values-pt-rPT-v33/strings.xml b/PermissionController/res/values-pt-rPT-v33/strings.xml
index cb7bac394..a228677bf 100644
--- a/PermissionController/res/values-pt-rPT-v33/strings.xml
+++ b/PermissionController/res/values-pt-rPT-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Mais alertas"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alertas ignorados"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Expandir e ver mais um alerta}many{Expandir e ver mais # alertas}other{Expandir e ver mais # alertas}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerta. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Ação concluída"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Verifique as definições que podem adicionar proteção ao seu dispositivo"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Definições rápidas de segurança e privacidade"</string>
diff --git a/PermissionController/res/values-pt-rPT/strings.xml b/PermissionController/res/values-pt-rPT/strings.xml
index 1c9eda5c6..22adec868 100644
--- a/PermissionController/res/values-pt-rPT/strings.xml
+++ b/PermissionController/res/values-pt-rPT/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Não permitir mesmo assim"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Ignorar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Permitir a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> sempre?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Permitir a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; o seguinte? <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permitir sempre isto à app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;? <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Apenas ao utilizar a app"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Sempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Não permitir e não perguntar novamente"</string>
@@ -126,7 +126,7 @@
<string name="app_name_unknown" msgid="1319665005754048952">"Desconhecido"</string>
<string name="permission_usage_title" msgid="1568233336351734538">"Painel de privacidade"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Veja que apps utilizaram autorizações recentemente"</string>
- <string name="permission_group_usage_title" msgid="2595013198075285173">"utilização de <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
+ <string name="permission_group_usage_title" msgid="2595013198075285173">"Utilização de <xliff:g id="PERMGROUP">%1$s</xliff:g>"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Veja outras autorizações"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> e mais <xliff:g id="NUM">%3$s</xliff:g>"</string>
@@ -351,43 +351,43 @@
<string name="role_assistant_short_label" msgid="3369003713187703399">"App assistente digital"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"As apps de assistência podem ajudá-lo com base em informações do ecrã que está a ver. Algumas apps são compatíveis com serviços de iniciação e de entrada de texto por voz para oferecer assistência integrada."</string>
<string name="role_browser_label" msgid="2877796144554070207">"App navegador predefinida"</string>
- <string name="role_browser_short_label" msgid="6745009127123292296">"Aplicação de navegador"</string>
+ <string name="role_browser_short_label" msgid="6745009127123292296">"App de navegador"</string>
<string name="role_browser_description" msgid="3465253637499842671">"Apps que lhe dão acesso à Internet e apresentam links em que pode tocar."</string>
- <string name="role_browser_request_title" msgid="2895200507835937192">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de navegador predefinida?"</string>
+ <string name="role_browser_request_title" msgid="2895200507835937192">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de navegador predefinida?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"Não são necessárias autorizações."</string>
<string name="role_dialer_label" msgid="1100224146343237968">"App de telefone predefinida"</string>
<string name="role_dialer_short_label" msgid="7186888549465352489">"App Telefone"</string>
<string name="role_dialer_description" msgid="8768708633696539612">"Apps que permitem efetuar e receber chamadas no seu dispositivo."</string>
- <string name="role_dialer_request_title" msgid="5959618560705912058">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de telefone predefinida?"</string>
+ <string name="role_dialer_request_title" msgid="5959618560705912058">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de telefone predefinida?"</string>
<string name="role_dialer_request_description" msgid="6288839625724909320">"Esta app fica com acesso à sua Câmara, Contactos, Microfone, Telefone e SMS"</string>
<string name="role_dialer_search_keywords" msgid="3324448983559188087">"telefone"</string>
<string name="role_sms_label" msgid="8456999857547686640">"App de SMS predefinida"</string>
- <string name="role_sms_short_label" msgid="4371444488034692243">"Aplicação de SMS"</string>
+ <string name="role_sms_short_label" msgid="4371444488034692243">"App de SMS"</string>
<string name="role_sms_description" msgid="3424020199148153513">"Apps que permitem utilizar o seu número de telefone para enviar e receber mensagens de texto, fotos, vídeos e muito mais."</string>
- <string name="role_sms_request_title" msgid="7953552109601185602">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como app SMS predefinida?"</string>
+ <string name="role_sms_request_title" msgid="7953552109601185602">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como app SMS predefinida?"</string>
<string name="role_sms_request_description" msgid="2691004766132144886">"Esta app fica com acesso à sua Câmara, Contactos, Ficheiros e multimédia, Microfone, Telefone e SMS"</string>
<string name="role_sms_search_keywords" msgid="8022048144395047352">"mensagem de texto, enviar mensagens de texto, mensagens"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"Aplicação de emergência pred."</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"Aplicação de emergência"</string>
<string name="role_emergency_description" msgid="5051840234887686630">"Apps que permitem registar as suas informações médicas e disponibilizá-las aos contactos de resposta a emergências, receber alertas acerca de eventos atmosféricos e desastres graves, bem como notificar outras pessoas quando precisar de ajuda."</string>
- <string name="role_emergency_request_title" msgid="8469579020654348567">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de emergência predefinida?"</string>
+ <string name="role_emergency_request_title" msgid="8469579020654348567">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de emergência predefinida?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"Não são necessárias autorizações."</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"em caso de emergência"</string>
<string name="role_home_label" msgid="3871847846649769412">"App página inicial predefinida"</string>
<string name="role_home_short_label" msgid="8544733747952272337">"App Página inicial"</string>
<string name="role_home_description" msgid="7997371519626556675">"Apps, frequentemente denominadas iniciadores, que substituem os ecrãs principais no dispositivo Android e dão acesso aos conteúdos e às funcionalidades do seu dispositivo."</string>
- <string name="role_home_request_title" msgid="738136983453341081">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app Página inicial predefinida?"</string>
+ <string name="role_home_request_title" msgid="738136983453341081">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app Página inicial predefinida?"</string>
<string name="role_home_request_description" msgid="2658833966716057673">"Não são necessárias autorizações."</string>
<string name="role_home_search_keywords" msgid="3830755001192666285">"iniciador"</string>
<string name="role_call_redirection_label" msgid="5785304207206147590">"Aplic. redirec. chamadas pred."</string>
<string name="role_call_redirection_short_label" msgid="7568143419571217757">"Aplic. de redirec. de chamadas"</string>
<string name="role_call_redirection_description" msgid="6091669882014664420">"Apps que permitem encaminhar chamadas efetuadas para outro número de telefone."</string>
- <string name="role_call_redirection_request_title" msgid="2816244455003562925">"Pretende definir <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de redirecionamento de chamadas predefinida?"</string>
+ <string name="role_call_redirection_request_title" msgid="2816244455003562925">"Quer definir <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de redirecionamento de chamadas predefinida?"</string>
<string name="role_call_redirection_request_description" msgid="3118895714178527164">"Não são necessárias autorizações."</string>
<string name="role_call_screening_label" msgid="883935222060878724">"App de filtro de chamadas e spam"</string>
<string name="role_call_screening_short_label" msgid="2048465565063130834">"App de ID de chamada e spam"</string>
<string name="role_call_screening_description" msgid="2349431420497468981">"Apps que lhe permitem identificar chamadas e bloquear spam, chamadas automáticas ou números indesejados."</string>
- <string name="role_call_screening_request_title" msgid="7358309224566977290">"Pretende definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de identificação de chamadas e spam predefinida?"</string>
+ <string name="role_call_screening_request_title" msgid="7358309224566977290">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de identificação de chamadas e spam predefinida?"</string>
<string name="role_call_screening_request_description" msgid="7338511921032446006">"Não são necessárias autorizações."</string>
<string name="role_automotive_navigation_label" msgid="2701890757955474751">"App de navegação predefinida"</string>
<string name="role_automotive_navigation_short_label" msgid="5165823092506922457">"App de navegação"</string>
@@ -437,11 +437,11 @@
<string name="special_app_access_no_apps" msgid="4102911722787886970">"Sem apps"</string>
<string name="home_missing_work_profile_support" msgid="1756855847669387977">"Não suporta o perfil de trabalho."</string>
<string name="encryption_unaware_confirmation_message" msgid="8274491794636402484">"Nota: se reiniciar o dispositivo e tiver um bloqueio de ecrã definido, só é possível iniciar esta app quando o dispositivo for desbloqueado."</string>
- <string name="assistant_confirmation_message" msgid="7476540402884416212">"O assistente pode ler informações sobre aplicações em utilização no seu sistema, incluindo informações visíveis no ecrã ou acessíveis nas aplicações."</string>
+ <string name="assistant_confirmation_message" msgid="7476540402884416212">"O assistente pode ler informações sobre as apps em utilização no seu sistema, incluindo informações visíveis no ecrã ou acessíveis nas apps."</string>
<string name="incident_report_channel_name" msgid="3144954065936288440">"Partilhar dados de depuração"</string>
- <string name="incident_report_notification_title" msgid="4635984625656519773">"Pretende partilhar dados de depuração detalhados?"</string>
- <string name="incident_report_notification_text" msgid="3376480583513587923">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> pretende carregar informações de depuração."</string>
- <string name="incident_report_dialog_title" msgid="669104389325204095">"Pretende partilhar dados de depuração?"</string>
+ <string name="incident_report_notification_title" msgid="4635984625656519773">"Quer partilhar dados de depuração detalhados?"</string>
+ <string name="incident_report_notification_text" msgid="3376480583513587923">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> quer carregar informações de depuração."</string>
+ <string name="incident_report_dialog_title" msgid="669104389325204095">"Quer partilhar dados de depuração?"</string>
<string name="incident_report_dialog_intro" msgid="5897733669850951832">"O sistema detetou um problema."</string>
<string name="incident_report_dialog_text" msgid="5675553296891757523">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> está a solicitar o carregamento de um relatório de erro a partir deste dispositivo realizado a <xliff:g id="DATE">%2$s</xliff:g> à(s) <xliff:g id="TIME">%3$s</xliff:g>. Os relatórios de erros incluem informações pessoais acerca do seu dispositivo ou registadas por app, por exemplo, nomes de utilizador, dados de localização, identificadores do dispositivo e informações da rede. Apenas partilhe relatórios de erros com pessoas e apps nas quais confia. Permite que a app <xliff:g id="APP_NAME_1">%4$s</xliff:g> carregue um relatório de erro?"</string>
<string name="incident_report_error_dialog_text" msgid="4189647113387092272">"Ocorreu um erro ao processar o relatório de erro para a app <xliff:g id="APP_NAME">%1$s</xliff:g>. Como tal, a partilha dos dados de depuração detalhados foi negada. Pedimos desculpa pela interrupção."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostre a deteção do acionador do assistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostre o ícone na barra de estado quando o microfone é utilizado para ativar o assistente de voz"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a fotos e multimédia no dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda aos seus contactos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda à localização deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"A app tem acesso à localização apenas enquanto a estiver a utilizar"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda à localização deste dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Esta app poderá pretender aceder sempre à sua localização, mesmo quando não a estiver a utilizar. "<annotation id="link">"Permita-o nas definições."</annotation></string>
- <string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Pretende alterar o acesso à localização para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
- <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Esta app pretende aceder sempre à sua localização, mesmo quando não a estiver a utilizar. "<annotation id="link">"Permita-o nas definições."</annotation></string>
+ <string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Quer alterar o acesso à localização para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Esta app quer aceder sempre à sua localização, mesmo quando não a estiver a utilizar. "<annotation id="link">"Permita-o nas definições."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, determine a posição relativa dos dispositivos próximos e se ligue aos mesmos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, determine a posição relativa dos dispositivos próximos e se ligue aos mesmos? "<annotation id="link">"Permita nas Definições."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Alterar o acesso à localização da app <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> de aproximada para exata?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda à localização aproximada deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exata"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda ao calendário?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envie e veja mensagens SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a fotos, multimédia e ficheiros no dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a &lt;b&gt;fotos, vídeos, música e áudio&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a &lt;b&gt;fotos, vídeos, música, áudio, etc.&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a música e áudio neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda a mais fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"A app apenas poderá gravar áudio enquanto a estiver a utilizar."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Esta app pode pretender gravar áudio sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
- <string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Pretende alterar o acesso ao microfone para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
- <string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Esta app pretende gravar áudio sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
+ <string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Quer alterar o acesso ao microfone para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Esta app quer gravar áudio sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aceda à sua atividade física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"A app apenas poderá tirar fotos e gravar vídeos enquanto a estiver a utilizar."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Permitir que a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Esta app pode pretender tirar fotos e gravar vídeos sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
- <string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Pretende alterar o acesso à câmara para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
- <string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Esta app pretende tirar fotos e gravar vídeos sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
+ <string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Quer alterar o acesso à câmara para a app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Esta app quer tirar fotos e gravar vídeos sempre, mesmo quando não a está a utilizar. "<annotation id="link">"Permita-o nas Definições."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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 de sensores acerca dos seus sinais vitais?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Para permitir que esta app aceda sempre aos dados de sensores de corpo, mesmo quando não está a usá-la, "<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="auto_granted_permissions" msgid="6009452264824455892">"Autorizações controladas"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Autorizações controladas"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> tem acesso à localização"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"A sua organização permite que a app <xliff:g id="APP_NAME">%1$s</xliff:g> aceda à sua localização"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Outras autorizações"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Autorização utilizada pelo sistema"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Autorizações utilizadas apenas pelas aplicações do sistema."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Esta app declarou que pode partilhar dados de localização com terceiros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Localização e partilha de dados"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Qual é a origem das informações da partilha de dados"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"O programador deu informações ao fabricante deste dispositivo sobre como esta app partilha dados. O programador pode atualizar estas informações ao longo do tempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"O programador forneceu informações a "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre como esta app partilha dados. O programador pode atualizar estas informações ao longo do tempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Esta app pode partilhar dados de localização para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"A partilha de dados varia"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Segurança dos dados"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Os dados de localização podem ser partilhados"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Esta app declarou que pode partilhar os seus dados de localização com terceiros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Não é possível abrir este link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Atualizações da partilha de dados para a localização"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Reveja apps que mudaram a forma como podem partilhar os seus dados de localização"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Estas apps mudaram a forma como podem partilhar os seus dados de localização. Podem não os ter partilhado antes ou podem partilhá-los agora para fins de publicidade ou marketing."</string>
diff --git a/PermissionController/res/values-pt-v33/strings.xml b/PermissionController/res/values-pt-v33/strings.xml
index 01a8edce9..aeda06c8f 100644
--- a/PermissionController/res/values-pt-v33/strings.xml
+++ b/PermissionController/res/values-pt-v33/strings.xml
@@ -40,7 +40,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Chave. <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g>. <xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Alternar"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Abrir"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Revisar configura&amp;#173;ções"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Revisar configura­ções"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Configurações"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Informações"</string>
</resources>
diff --git a/PermissionController/res/values-pt/strings.xml b/PermissionController/res/values-pt/strings.xml
index f0a018192..5a51eb1d5 100644
--- a/PermissionController/res/values-pt/strings.xml
+++ b/PermissionController/res/values-pt/strings.xml
@@ -34,14 +34,14 @@
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Mais inform."</string>
<string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Permitir tudo"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Sempre permitir tudo"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Alguns vídeos e fotos"</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Selecionar fotos e vídeos"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Selecionar mais"</string>
<string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Não selecionar mais"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Não permitir mesmo assim"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Dispensar"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> de <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Sempre permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Permitir o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Sempre permitir o acesso de &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; a: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Apenas ao usar o app"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Sempre"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Não permitir e não perguntar de novo"</string>
@@ -198,7 +198,7 @@
<string name="app_permission_title" msgid="2090897901051370711">"Permissão para acessar <xliff:g id="PERM">%1$s</xliff:g>"</string>
<string name="app_permission_header" msgid="2951363137032603806">"Permitir que este app acesse: <xliff:g id="PERM">%1$s</xliff:g>"</string>
<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="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar 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>
@@ -369,7 +369,7 @@
<string name="role_sms_search_keywords" msgid="8022048144395047352">"mensagem de texto, enviar mensagens de texto, mensagens"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"App padrão de emergência"</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"App de emergência"</string>
- <string name="role_emergency_description" msgid="5051840234887686630">"Apps que permitem registrar informações médicas e disponibilizá-las para socorristas, receber alertas sobre eventos climáticos graves e desastres e notificar outras pessoas se você precisar de ajuda"</string>
+ <string name="role_emergency_description" msgid="5051840234887686630">"Apps que permitem registrar informações de saúde e disponibilizá-las para socorristas, receber alertas sobre eventos climáticos graves e desastres e notificar outras pessoas se você precisar de ajuda"</string>
<string name="role_emergency_request_title" msgid="8469579020654348567">"Definir <xliff:g id="APP_NAME">%1$s</xliff:g> como app padrão de emergência?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"Nenhuma permissão necessária"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"em emergências"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Mostrar detecção de gatilho do assistente"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Mostrar ícone na barra de status quando o microfone for usado para ativar o assistente por voz"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos e mídia no seu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse seus contatos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse a localização deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"O app só terá acesso ao local enquanto estiver sendo usado"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse a localização deste dispositivo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Este app pode querer acessar sua localização o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita o acesso nas configurações"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Mudar o acesso que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem à localização?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Este app quer acessar sua localização o tempo todo, mesmo quando não estiver em uso. "<annotation id="link">"Permita o acesso nas configurações"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, conecte-se e determine a posição relativa de dispositivos por perto?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; encontre, conecte-se e determine a posição relativa de dispositivos por perto? "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Permitir a troca para que o app <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> acesse o local exato (em vez do aproximado)?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse o local aproximado deste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exata"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximada"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse sua agenda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse e envie mensagens SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos, mídia e arquivos no seu dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse &lt;b&gt;fotos, vídeos, músicas e áudios&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse &lt;b&gt;fotos, vídeos, músicas, áudios e outros arquivos&lt;/b&gt; neste dispositivo?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse músicas e áudios neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse mais fotos e vídeos neste dispositivo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"O app poderá gravar áudio apenas quando estiver em uso"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Este app pode querer gravar áudio a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Mudar o acesso que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem ao microfone?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Este app quer gravar áudio a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acesse sua atividade física?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Permitir que o app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"O app poderá tirar fotos e gravar vídeos apenas quando estiver em uso"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Este app pode querer tirar fotos e gravar vídeos a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Mudar o acesso que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tem à câmera?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Este app quer tirar fotos e gravar vídeos a qualquer momento, mesmo quando não estiver em uso. "<annotation id="link">"Permita nas configurações."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Permissões controladas"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> tem acesso à localização"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Sua organização permite que o app <xliff:g id="APP_NAME">%1$s</xliff:g> tenha acesso à sua localização"</string>
@@ -508,7 +562,7 @@
<string name="privdash_label_camera" msgid="1426440033626198096">"Câmera"</string>
<string name="privdash_label_microphone" msgid="8415035835803511693">"Microfone"</string>
<string name="privdash_label_location" msgid="6882400763866489291">"Localização"</string>
- <string name="privdash_label_other" msgid="3710394147423236033">"Outra"</string>
+ <string name="privdash_label_other" msgid="3710394147423236033">"Outras"</string>
<string name="privdash_label_none" msgid="5991866260360484858">"Nenhuma"</string>
<string name="privdash_label_24h" msgid="1512532123865375319">"Últimas\n24 horas"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Nos últimos\nsete dias"</string>
@@ -532,7 +586,7 @@
<string name="security_settings" msgid="3808106921175271317">"Configurações de segurança"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"Permissões"</string>
<string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"Segurança e privacidade"</string>
- <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Ver status"</string>
+ <string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Checar status"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Seus controles de privacidade"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Mais configurações"</string>
<string name="camera_toggle_label_qs" msgid="3880261453066157285">"Acesso à câmera"</string>
@@ -547,7 +601,7 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"Usada recentemente por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"Uso recente por <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"Usada recentemente por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>)"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"Em uso por <xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string>
@@ -575,7 +629,7 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Revisar apps com acesso à localização em segundo plano"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Este app sempre pode acessar sua localização, mesmo quando está fechado.\n\nAlguns apps de segurança e emergência exigem acesso à sua localização em segundo plano para funcionar corretamente."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"O acesso foi mudado"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Ver o uso recente da localização"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Verificar o uso recente da localização"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Controles de privacidade"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Acesso à câmera"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Acesso ao microfone"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Este app declarou que pode compartilhar dados de local com terceiros"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Local e compartilhamento de dados"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De onde vêm as informações do compartilhamento de dados"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"O desenvolvedor forneceu informações para o fabricante do dispositivo sobre como este app compartilha dados. O desenvolvedor pode atualizar essas informações com o tempo."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"O desenvolvedor forneceu informações para "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" sobre como esse app compartilha dados. O desenvolvedor pode atualizar essas informações com o tempo."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Esse app pode compartilhar dados de local para:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"O compartilhamento de dados varia"</string>
@@ -606,10 +661,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Segurança dos dados"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Os dados de local podem ser compartilhados"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Este app indicou que pode compartilhar seus dados de local com terceiros"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Não é possível abrir esse link"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Atualizações no compartilhamento de dados de local"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"Revise os apps que mudaram a forma de compartilhar os dados de local"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"Conferir apps que mudaram a forma de compartilhar dados de local"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Esses apps mudaram a forma de compartilhar os dados de local. É possível que eles não tenham compartilhado antes ou que agora compartilhem para fins de publicidade ou marketing."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Os desenvolvedores desses apps oferecem informações sobre as práticas deles de compartilhamento de dados com uma app store. Eles podem atualizar essas informações com o tempo.\n\nAs práticas de compartilhamento de dados podem variar de acordo com a versão do app e com a idade, o uso e a região do usuário."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Saiba mais sobre o compartilhamento de dados"</string>
diff --git a/PermissionController/res/values-ro-v33/strings.xml b/PermissionController/res/values-ro-v33/strings.xml
index 3715a4414..a32a32db5 100644
--- a/PermissionController/res/values-ro-v33/strings.xml
+++ b/PermissionController/res/values-ro-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Mai multe alerte"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Alerte respinse"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Extinde și mai vezi o alertă}few{Extinde și mai vezi # alerte}other{Extinde și mai vezi # de alerte}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alertă. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Acțiune încheiată"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Verifică setările care pot spori protecția dispozitivului"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Setări rapide privind securitatea și confidențialitatea"</string>
diff --git a/PermissionController/res/values-ro/strings.xml b/PermissionController/res/values-ro/strings.xml
index d0a18327a..baedb5f88 100644
--- a/PermissionController/res/values-ro/strings.xml
+++ b/PermissionController/res/values-ro/strings.xml
@@ -34,14 +34,14 @@
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Mai multe info."</string>
<string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Permite-le pe toate"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Permite-le întotdeauna pe toate"</string>
- <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Alege fotografii și videoclipuri."</string>
+ <string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Alege fotografii și videoclipuri"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Selectează mai multe"</string>
<string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Nu selecta mai multe"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Nu permite în nicio situație"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Închide"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> din <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="permission_warning_template" msgid="2247087781222679458">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permiți întotdeauna &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Permiți întotdeauna ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Doar când folosești aplicația"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Mereu"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Nu permite și nu mai întreba"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Afișează detectarea declanșării asistentului"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Afișează pictograma în bara de stare când microfonul este folosit pentru a activa asistentul vocal"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze fotografiile și conținutul media de pe dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să-ți acceseze agenda?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze locația acestui dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplicația va avea acces la locație doar când o folosești"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze locația acestui dispozitiv?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"E posibil ca aplicația să dorească să-ți acceseze în permanență locația, chiar și când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Modifici accesul la locație pentru &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Aplicația dorește să-ți acceseze în permanență locația, chiar și când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să găsească, să se conecteze la și să afle poziția relativă a dispozitivelor apropiate?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să găsească, să se conecteze la și să determine poziția relativă a dispozitivelor apropiate? "<annotation id="link">"Permite în setări."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Schimbi permisiunile privind accesul la locație pentru <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> de la locația aproximativă la cea exactă?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze locația aproximativă a acestui dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exactă"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Aproximativă"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze calendarul?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să trimită și să vadă mesaje SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze fotografiile, conținutul media și fișierele de pe dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Permiți accesul &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; la &lt;b&gt;fotografii, clipuri, conținut audio și muzică&lt;/b&gt; de pe dispozitiv?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Permiți accesul &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; la &lt;b&gt;fotografii, clipuri, conținut audio, muzică și alte fișiere&lt;/b&gt; de pe dispozitiv?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Permiți accesul &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; la muzică și fișiere audio de pe acest dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze fotografiile și videoclipurile de pe dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să acceseze mai multe fotografii și videoclipuri de pe dispozitiv?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să înregistreze audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplicația va putea să înregistreze conținut audio doar când o folosești"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să înregistreze audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Aplicația poate dori să înregistreze conținut audio permanent, chiar și când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Modifici accesul la microfon pentru &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Aplicația dorește să înregistreze conținut audio permanent, chiar și când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Permiți aplicației &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să-ți acceseze activitatea fizică?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să fotografieze și să înregistreze video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplicația va putea să fotografieze și să înregistreze videoclipuri doar când o folosești"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să facă fotografii și să înregistreze videoclipuri?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Aplicația poate dori să fotografieze și să înregistreze videoclipuri permanent, chiar când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Modifici accesul la camera foto pentru &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Aplicația dorește să fotografieze și să înregistreze videoclipuri permanent, chiar și când nu o folosești. "<annotation id="link">"Acordă această permisiune din setări."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să-ți acceseze jurnalele de apeluri?"</string>
- <string name="permgrouprequest_phone" msgid="1829234136997316752">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să facă și să gestioneze apeluri telefonice?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
+ <string name="permgrouprequest_phone" msgid="1829234136997316752">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să dea și să gestioneze apeluri telefonice?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Permiț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 vitale?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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 folosești. Pentru a face această modificare, "<annotation id="link">"accesează setările"</annotation>"."</string>
<string name="permgroupbackgroundrequest_sensors" msgid="5661924322018503886">"Permiț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 vitale?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Pentru a permite accesul permanent al aplicației la datele de la senzorii corporali, chiar și atunci când nu o folosești, "<annotation id="link">"accesează setările"</annotation>"."</string>
<string name="permgroupupgraderequest_sensors" msgid="7576527638411370468">"Permiț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">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să-ți trimită notificări?"</string>
- <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisiuni controlate"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Permiți ca &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să-ți trimită notificări?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Permisiuni controlate"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> are acces la locație"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organizația ta permite ca <xliff:g id="APP_NAME">%1$s</xliff:g> să-ți acceseze locația"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Alte permisiuni"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Permisiuni folosite de sistem"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Permisiuni folosite numai de aplicațiile sistemului."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Aplicația afirmă că poate trimite terților date privind locațiile"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Locația și permiterea accesului la date"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"De unde provin informațiile despre permiterea accesului la date"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Dezvoltatorul a trimis producătorului acestui dispozitiv informații despre modul în care această aplicație permite accesul la date. Dezvoltatorul poate actualiza informațiile în timp."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Dezvoltatorul a trimis la "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" informații despre modul în care această aplicație permite accesul la date. Dezvoltatorul poate actualiza informațiile în timp."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Aplicația poate permite accesul la date pentru:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Permiterea accesului la date variază"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Siguranța datelor"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Se poate permite accesul la datele privind locațiile tale"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Aplicația afirmă că le poate trimite terților date privind locațiile tale"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Linkul nu poate fi deschis"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Actualizări privind permiterea accesului la date pentru locație"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Examinează aplicațiile care au schimbat modul în care pot permite accesul la datele tale privind locațiile"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Aceste aplicații au schimbat modul în care pot permite accesul la datele tale privind locațiile. Este posibil să nu fi permis accesul la ele anterior sau să-l permită acum în scopuri de publicitate sau de marketing."</string>
diff --git a/PermissionController/res/values-ru-v33/strings.xml b/PermissionController/res/values-ru-v33/strings.xml
index 9f74baf9a..a13e4e8d5 100644
--- a/PermissionController/res/values-ru-v33/strings.xml
+++ b/PermissionController/res/values-ru-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Другие оповещения"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Закрытые оповещения"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Разверните, чтобы увидеть ещё одно оповещение}one{Разверните, чтобы увидеть ещё # оповещение}few{Разверните, чтобы увидеть ещё # оповещения}many{Разверните, чтобы увидеть ещё # оповещений}other{Разверните, чтобы увидеть ещё # оповещения}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Оповещение. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Действие выполнено"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Изучите настройки, позволяющие усилить защиту устройства"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Быстрые настройки безопасности и конфиденциальности"</string>
diff --git a/PermissionController/res/values-ru-v34/strings.xml b/PermissionController/res/values-ru-v34/strings.xml
index 931ebb6d5..64a927b69 100644
--- a/PermissionController/res/values-ru-v34/strings.xml
+++ b/PermissionController/res/values-ru-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Защита и конфиденциальность"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Настройки"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Здоровье и спорт"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Настроить доступ приложения к данным о здоровье"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Настроить доступ приложений к данным о здоровье"</string>
<string name="location_settings" msgid="8863940440881290182">"Доступ к геоданным"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Для приложений и сервисов. Даже если эта функция отключена, данные микрофона могут передаваться при звонке на номер экстренной службы."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Для приложений и сервисов"</string>
diff --git a/PermissionController/res/values-ru/strings.xml b/PermissionController/res/values-ru/strings.xml
index c276dd5cf..451588df8 100644
--- a/PermissionController/res/values-ru/strings.xml
+++ b/PermissionController/res/values-ru/strings.xml
@@ -32,11 +32,11 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"Оставить доступ только в активном режиме"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"Оставить \"Только в этот раз\""</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Подробнее"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Разрешить все"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Разрешить ко всем"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Постоянный полный доступ"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Выбрать фотографии и видео"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Выбрать больше"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Больше не выбирать"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Не выбирать"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Все равно запретить"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Закрыть"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> из <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Разрешить в любом режиме"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Только во время использования"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Разрешить только во время использования приложения"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Запретить"</string>
<string name="loading" msgid="4789365003890741082">"Загрузка…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Все разрешения"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Использовалось <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Если вы разрешите приложению управлять всеми файлами, оно сможет просматривать, изменять и удалять любые файлы в общем хранилище на этом устройстве, а также на подключенных запоминающих устройствах. При этом оно сможет получать доступ к файлам без вашего ведома."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Разрешить этому приложению просматривать, изменять и удалять любые файлы на этом устройстве, а также на подключенных запоминающих устройствах? Приложение сможет получать доступ к файлам без вашего ведома."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Приложения с разрешением <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Приложения с этим разрешением <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Приложения с этим разрешением могут получать доступ к данным о вашей физической активности, включая количество пройденных шагов и продолжительность прогулок и поездок на велосипеде."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Приложения с этим разрешением могут получать доступ к календарю."</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Приложения с этим разрешением могут читать список вызовов и создавать записи в нем."</string>
@@ -263,7 +263,7 @@
<string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"Разрешения отозваны для защиты конфиденциальности ваших данных. Нажмите, чтобы узнать больше."</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"У неиспользуемых приложений отозваны разрешения"</string>
<string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"Вы уже несколько месяцев не используете некоторые приложения. Нажмите, чтобы посмотреть подробности."</string>
- <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# неиспользуемое приложение}one{# неиспользуемое приложение}few{# неиспользуемого приложения}many{# неиспользуемых приложений}other{# неиспользуемого приложения}}"</string>
+ <string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# неиспользуемое приложение}one{# неиспользуемое приложение}few{# неиспользуемых приложения}many{# неиспользуемых приложений}other{# неиспользуемого приложения}}"</string>
<string name="unused_apps_notification_content" msgid="9195026773244581246">"Мы отозвали разрешения, удалили временные файлы и отключили уведомления. Нажмите, чтобы узнать подробности."</string>
<string name="unused_apps_safety_center_card_title" msgid="5638409355530099149">"Проверьте приложения с отозванными разрешениями"</string>
<string name="unused_apps_safety_center_card_content" msgid="1088557243627427820">"Мы отозвали разрешения, удалили временные файлы и отключили уведомления для приложений, которые вы давно не использовали."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Показывать значок активации голосового помощника"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Показывать значок в строке состояния, когда для активации голосового помощника используется микрофон"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фото и мультимедиа на устройстве?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к контактам?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным о местоположении устройства?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Доступ к местоположению будет открыт, только пока вы пользуетесь приложением."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным о местоположении устройства?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Этому приложению может потребоваться доступ к вашему местоположению, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Изменить настройки доступа к данным о местоположении для приложения &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Этому приложению требуется доступ к вашему местоположению, даже когда вы им не пользуетесь. Предоставьте разрешение в "<annotation id="link">"настройках"</annotation>"."</string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" находить устройства поблизости, подключаться к ним и определять их относительное положение?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Разрешить приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" находить устройства поблизости, подключаться к ним и определять их относительное позиционирование? "<annotation id="link">"Открыть настройки"</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; находить устройства поблизости, подключаться к ним и определять их относительное положение?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; находить устройства поблизости, подключаться к ним и определять их относительное положение? "<annotation id="link">"Открыть настройки"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Изменить местоположение в приложении \"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\" с приблизительного на точное?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным о приблизительном местоположении устройства?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Точно"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Приблизительно"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к календарю?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; отправлять и просматривать SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фото, мультимедиа и файлам на устройстве?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к &lt;b&gt;фото, видео, музыке и аудио&lt;/b&gt; на устройстве?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к &lt;b&gt;фото, видео, аудио и другим файлам&lt;/b&gt; на устройстве?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к музыке и аудио на устройстве?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фото и видео на устройстве?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к фотографиям и видео на этом устройстве?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к другим фото и видео на этом устройстве?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записывать аудио?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Приложение будет записывать аудио, только когда вы им пользуетесь."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записывать аудио?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Это приложение может записывать аудио в любое время, даже когда вы им не пользуетесь. "<annotation id="link">"Предоставьте разрешение в настройках."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Изменить настройки доступа к микрофону для приложения &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Это приложение записывает аудио в любое время, даже когда вы им не пользуетесь. "<annotation id="link">"Предоставьте разрешение в настройках."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным о физической активности?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снимать фото и видео?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Приложение будет делать фотографии и снимать видео, только когда вы им пользуетесь."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снимать фото и видео?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Это приложение может делать фотографии и снимать видео в любое время, даже когда вы им не пользуетесь. "<annotation id="link">"Предоставьте разрешение в настройках."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Изменить настройки доступа к камере для приложения &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Это приложение делает фотографии и снимает видео в любое время, даже когда вы им не пользуетесь. "<annotation id="link">"Предоставьте разрешение в настройках."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к списку вызовов?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; совершать звонки и управлять ими?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ к данным датчиков о состоянии организма?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Чтобы предоставить приложению доступ к данным нательных датчиков, даже когда вы им не пользуетесь, "<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="auto_granted_permissions" msgid="6009452264824455892">"Контролируемые разрешения"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Разрешить <xliff:g id="APP_NAME">%1$s</xliff:g> отправлять уведомления?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Контролируемые разрешения"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"У приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" есть доступ к геоданным"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"В вашей организации приложению \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" разрешен доступ к геоданным."</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Другие разрешения"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Разрешения, используемые системой"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Разрешения, используемые только системными приложениями"</string>
@@ -577,7 +629,7 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Проверьте приложение с доступом к геоданным в фоновом режиме"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"У этого приложения есть доступ к геоданным, даже когда оно закрыто.\n\nНекоторым приложениям, которые обеспечивают безопасность или предназначены для экстренных случаев, требуется доступ к данным о вашем местоположении в фоновом режиме, чтобы правильно выполнять свои функции."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Права доступа изменены."</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Показать сведения о недавнем использовании геоданных"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Показать недавнее использование геоданных"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Настройки конфиденциальности"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Доступ к камере"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Доступ к микрофону"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Это приложение может передавать третьим лицам данные о местоположении."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Передача данных и местоположение"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Источник сведений о передаче данных"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Разработчик предоставил производителю устройства информацию о том, как приложение передает данные. Со временем он может ее обновить."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Разработчик предоставил "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" информацию о том, как приложение передает данные. Со временем она может обновляться."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Цели передачи данных о местоположении:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Варианты передачи данных"</string>
@@ -608,9 +661,7 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Безопасность данных"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Возможна передача геоданных"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Это приложение уведомило, что оно может передавать данные о вашем местоположении третьим лицам."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Не удалось открыть ссылку"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
- <string name="data_sharing_updates_title" msgid="7996933386875213859">"Обновление сведений о передаче данных о местоположении"</string>
+ <string name="data_sharing_updates_title" msgid="7996933386875213859">"Обновления в передаче данных о местоположении"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Проверить приложения, которые изменили подход к передаче данных о вашем местоположении"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Эти приложения изменили подход к передаче данных о вашем местоположении. Возможно, такие сведения ранее не передавались или теперь передаются в рекламных или маркетинговых целях."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Разработчики этих приложений предоставили магазину информацию о своем подходе к передаче данных. Эти сведения могут обновляться.\n\nПодход к передаче данных может зависеть от версии приложения, способа его использования, а также от вашего региона и возраста."</string>
diff --git a/PermissionController/res/values-si-v33/strings.xml b/PermissionController/res/values-si-v33/strings.xml
index e7eb6d8fb..b3d1ab958 100644
--- a/PermissionController/res/values-si-v33/strings.xml
+++ b/PermissionController/res/values-si-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"තවත් ඇඟවීම්"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"අස් කළ ඇඟවීම්"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{පුළුල් කර තවත් එක් ඇඟවීමක් බලන්න}one{පුළුල් කර තවත් ඇඟවීම් #ක් බලන්න}other{පුළුල් කර තවත් ඇඟවීම් #ක් බලන්න}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"ඇඟවීම. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"ක්‍රියාමාර්ගය සම්පූර්ණයි"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ඔබේ උපාංගයට ආරක්ෂණය එක් කළ හැකි සැකසීම් පරීක්ෂා කරන්න"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"ආරක්ෂාව සහ පෞද්ගලිකත්වය ඉක්මන් සැකසීම්"</string>
diff --git a/PermissionController/res/values-si/strings.xml b/PermissionController/res/values-si/strings.xml
index 04b2545ba..8295bb58b 100644
--- a/PermissionController/res/values-si/strings.xml
+++ b/PermissionController/res/values-si/strings.xml
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"අවසාන විවෘත කළේ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"ඔබ සියලු ගොනු කළමනාකරණය කිරීමට ඉඩ දෙන්නේ නම්, මෙම යෙදුමට මෙම උපාංගයේ හෝ සම්බන්ධිත ගබඩා උපාංගවල පොදු ගබඩාවේ ඇති ඕනෑම ගොනුවක් වෙත ප්‍රවේශ වීමට, වෙනස් කිරීමට සහ මැකීටම හැකිය. යෙදුම ඔබෙන් විමසීමෙන් තොරව ගොනු වෙත ප්‍රවේශ විය හැකිය."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"මෙම යෙදුමට උපාංගයේ හෝ ඕනෑම සම්බන්ධිත ගබඩා උපාංගයක ඇති ගොනු වෙත ප්‍රවේශ වීමට, වෙනස් කිරීමට සහ මැකීමට ඉඩ දෙන්නද? මෙම යෙදුම ඔබෙන් විමසීමෙන් තොරව ගොනු වෙත ප්‍රවේශ විය හැකිය."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"මෙම අවසරය සහිත යෙදුම්වලට <xliff:g id="DESCRIPTION">%1$s</xliff:g> කළ හැක"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"මෙම අවසරය ඇති යෙදුම් වලට මෙය කළ හැක: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"මෙම අවසරය සහිත යෙදුම්වලට ඇවිදීම, බයිසිකල් පැදීම, රිය පැදවීම, පියවර ගණනය සහ තවත් දෑ වැනි, ඔබේ ශාරීරික ක්‍රියාකාරකම්වලට ප්‍රවේශ විය හැක"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"මෙම අවසරය සහිත යෙදුම්වලට ඔබේ දින දර්ශනය වෙත ප්‍රවේශ විය හැක"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"මෙම අවසරය සහිත යෙදුම්වලට දුරකථන ඇමතුම් ලොගය කියවීමටත් ලිවීමටත් හැකි ය"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"සහායක ප්‍රේරකය අනාවරණය පෙන්වන්න"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"හඬ සහායක සක්‍රිය කිරීමට මයික්‍රෆෝනය භාවිතා කරන විට තත්ත්ව තීරුවේ නිරූපකය පෙන්වන්න"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ උපාංගය තුළ ඇති ඡායාරූප, මාධ්‍ය, සහ ගොනු වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නේද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ සබඳතා වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයෙහි ස්ථානය වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"ඔබ යෙදුම භාවිත කරන විට පමණක් යෙදුමට ස්ථානය වෙත ප්‍රවේශය ඇත"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයෙහි ස්ථානය වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"මෙයට ඔබ යෙදුම භාවිත නොකරමින් සිටින විට පවා සියලු අවස්ථාවල ඔබේ ස්ථානය වෙත ප්‍රවේශ වීමට අවශ්‍ය විය හැකිය. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; සඳහා ස්ථාන ප්‍රවේශය වෙනස් කරන්නද?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"මෙම යෙදුමට ඔබ යෙදුම භාවිත නොකරමින් සිටින විට පවා සියලු අවස්ථාවල ඔබේ ස්ථානය වෙත ප්‍රවේශ වීමට අවශ්‍යයි. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට අවට උපාංග සොයා ගැනීමට, සම්බන්ධ වීමට සහ ඒවායේ සාපේක්ෂ ස්ථානය සොයා ගැනීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට අවට උපාංග සොයා ගැනීමට, සම්බන්ධ වීමට සහ ඒවායේ සාපේක්ෂ ස්ථානය සොයා ගැනීමට ඉඩ දෙන්නද? "<annotation id="link">"සැකසීම් තුළ ඉඩ දෙන්න."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> හි ස්ථානය ආසන්න සිට නිවැරදි දක්වා වෙනස් කරන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ට මෙම උපාංගයෙහි ස්ථානය වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ඉතා නිවැරදි"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"ආසන්න"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ දින දර්ශනය ප්‍රවේශ කිරීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත SMS පණිවිඩ යැවීමට සහ බැලීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ උපාංගය තුළ ඇති ඡායාරූප, මාධ්‍ය, සහ ගොනු වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයේ &lt;b&gt;ඡායාරූප, වීඩියෝ, සංගීතය සහ ශ්‍රව්‍ය&lt;b&gt; වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයේ &lt;b&gt;ඡායාරූප, වීඩියෝ, සංගීතය, ශ්‍රව්‍ය සහ වෙනත් ගොනු&lt;b&gt; වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයේ සංගීතය සහ ශ්‍රව්‍ය වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට මෙම උපාංගයේ ඇති ඡායාරූප සහ වීඩියෝ වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට මෙම උපාංගයෙහි ඇති තවත් ඡායාරූප සහ වීඩියෝ වෙත ප්‍රවේශ වීමට ඉඩ දෙන්න ද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ශබ්දය පටි ගත කිරීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"යෙදුමට ඔබ යෙදුම භාවිත කරන අතරතුර ඕඩියෝ පටිගත කිරීමට පමණක් හැකි වනු ඇත"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට ඕඩියෝ පටිගත කිරීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"මෙම යෙදුමට ඔබ යෙදුම භාවිත කරමින් නොසිටින විට පවා මුළු කාලය පුරාම ඕඩියෝ පටිගත කිරීමට අවශ්‍ය විය හැකිය. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; සඳහා මයික්‍රෆෝන ප්‍රවේශය වෙනස් කරන්නද?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"මෙම යෙදුමට ඔබ යෙදුම භාවිත කරමින් නොසිටින විට පවා මුළු කාලය පුරාම ඕඩියෝ පටිගත කිරීමට අවශ්‍යයි. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට ඔබේ ශාරීරික ක්‍රියාකාරකමට ප්‍රවේශ වීමට ඉඩ දෙන්නේද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත පින්තූර සහ වීඩියෝ ගැනීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"යෙදුමට ඔබ යෙදුම භාවිත කරන අතරතුර පින්තූර ගැනීමට සහ වීඩියෝ පටිගත කිරීමට පමණක් හැකි වනු ඇත"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; හට පින්තූර ගැනීමට සහ වීඩියෝ පටිගත කිරීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"මෙම යෙදුමට ඔබ යෙදුම භාවිත කරමින් නොසිටින විට පවා මුළු කාලය පුරාම පින්තූර ගැනීමට සහ වීඩියෝ පටිගත කිරීමට අවශ්‍ය විය හැකිය. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; සඳහා කැමරා ප්‍රවේශය වෙනස් කරන්නද?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"මෙම යෙදුමට ඔබ යෙදුම භාවිත කරමින් නොසිටින විට පවා මුළු කාලය පුරාම පින්තූර ගැනීමට සහ වීඩියෝ පටිගත කිරීමට අවශ්‍යයි. "<annotation id="link">"සැකසීම්වල ඉඩ දෙන්න."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; ඔබේ ඇමතුම් ලොග වෙත පිවිසීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත දුරකථන ඇමතුම් ලබා ගැනීමට සහ කළමනාකරණය කිරීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ඔබගේ ජෛව ලක්ෂණ පිළිබඳ සංවේදක දත්ත වෙත ප්‍රවේශ වීමට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"ඔබ යෙදුම භාවිත නොකරන විට පවා, මෙම යෙදුමට ශරීර සංවේදක දත්තවලට ප්‍රවේශ වීමට ඉඩ දීමට, "<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="auto_granted_permissions" msgid="6009452264824455892">"පාලිත අවසර"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"ඔබට දැනුම්දීම් එවීමට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; හට ඉඩ දෙන්නද?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"පාලිත අවසර"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> හට ස්ථාන ප්‍රවේශය ඇත"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"ඔබේ සංවිධානය <xliff:g id="APP_NAME">%1$s</xliff:g> හට ඔබේ ස්ථානයට ප්‍රවේශ වීමට ඉඩ දෙයි"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"වෙනත් අවසර"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"පද්ධතිය මගින් භාවිත කරන අවසරය"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"පද්ධති යෙදුම් මගින් පමණක් භාවිත කරන අවසර."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"මෙම යෙදුම තෙවන පාර්ශ්වයන් සමග ස්ථාන දත්ත බෙදා ගත හැකි බව ප්‍රකාශ කර ඇත"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"දත්ත බෙදා ගැනීම සහ ස්ථානය"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"දත්ත බෙදා ගැනීමේ තතු පැමිණෙන තැන"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"සංවර්ධකයා මෙම යෙදුම දත්ත බෙදා ගන්නා ආකාරය පිළිබඳ තතු මෙම උපාංගයේ නිෂ්පාදකයාට ලබා දුන්නේ ය. සංවර්ධකයා මෙම තතු කාලයත් සමග යාවත්කාලීන කිරීමට ඉඩ ඇත."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"මෙම යෙදුම දත්ත බෙදා ගන්නා ආකාරය පිළිබඳව සංවර්ධකයා "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" වෙත තතු සපයා ඇත. සංවර්ධකයා මෙම තතු කාලයත් සමග යාවත්කාලීන කළ හැක."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"මෙම යෙදුම මේ සඳහා ස්ථාන දත්ත බෙදා ගත හැක:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"දත්ත බෙදා ගැනීම වෙනස් වේ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"දත්ත ආරක්ෂාව"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"ස්ථාන දත්ත බෙදා ගත හැක"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"මෙම යෙදුම තෙවන පාර්ශ්වයන් සමග ඔබේ ස්ථාන දත්ත බෙදා ගත හැකි බව ප්‍රකාශ කර ඇත"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"මෙම සබැඳිය විවෘත කළ නොහැක"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"ස්ථානය සඳහා දත්ත බෙදා ගැනීමේ යාවත්කාලීන"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ඒවා ඔබේ ස්ථාන දත්ත බෙදා ගත හැකි ආකාරය වෙනස් කළ යෙදුම් සමාලෝචනය කරන්න"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"මෙම යෙදුම් ඔබේ ස්ථාන දත්ත බෙදා ගත හැකි ආකාරය වෙනස් කර ඇත. ඒවා එය කලින් බෙදා ගෙන නොතිබිය හැක, නැතහොත් දැන් එය වෙළඳ ප්‍රචාරණ හෝ අලෙවිකරණ අරමුණු සඳහා බෙදා ගත හැක."</string>
diff --git a/PermissionController/res/values-sk/strings.xml b/PermissionController/res/values-sk/strings.xml
index 014feced7..8ec55e319 100644
--- a/PermissionController/res/values-sk/strings.xml
+++ b/PermissionController/res/values-sk/strings.xml
@@ -40,7 +40,7 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Aj tak nepovoliť"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Zavrieť"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> z <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vykonať akciu <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"Vždy povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Iba počas používania aplikácie"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Vždy"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Zobrazovať detekciu spustenia asistenta"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Zobrazovať v stavovom riadku ikonu, keď bude pomocou mikrofónu aktivovaný hlasový asistent"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k fotkám a médiám v zariadení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup ku kontaktom?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k polohe tohto zariadenia?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikácia bude mať prístup k polohe iba vtedy, keď ju budete používať"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k polohe tohto zariadenia?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Táto aplikácia môže požadovať nepretržitý prístup k vašej polohe, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Chcete zmeniť prístup k polohe pre aplikáciu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Táto aplikácia požaduje nepretržitý prístup k vašej polohe, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Chcete aplikácii <xliff:g id="APP_NAME">%1$s</xliff:g> povoliť vyhľadávať zariadenia v okolí, pripájať sa k nim a určovať ich relatívnu polohu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Chcete aplikácii <xliff:g id="APP_NAME">%1$s</xliff:g> povoliť vyhľadávať zariadenia v okolí, pripájať sa k nim a určovať ich vzájomnú polohu? "<annotation id="link">"Urobte to v nastaveniach."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Chcete zmeniť prístup k polohe aplikácie <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> z približnej polohy na presnú?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k približnej polohe tohto zariadenia?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Presná"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Približná"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup ku kalendáru?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; odosielať a zobrazovať správy SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k fotkám, médiám a súborom v zariadení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k &lt;b&gt;fotkám, videám, hudbe a zvuku&lt;/b&gt; v tomto zariadení?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k &lt;b&gt;fotkám, videám, hudbe, zvuku a ďalším súborom&lt;/b&gt; v tomto zariadení?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k hudbe a zvuku v tomto zariadení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k fotkám a videám v tomto zariadení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k ďalším fotkám a videám v tomto zariadení?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nahrávať zvuk?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Táto aplikácia bude môcť nahrávať zvuk iba vtedy, keď ju budete používať"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nahrávať zvuk?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Táto aplikácia môže požadovať nepretržitý prístup k nahrávaniu zvuku, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Chcete aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; zmeniť prístup k mikrofónu?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Táto aplikácia požaduje nepretržitý prístup k nahrávaniu zvuku, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prístup k vašej fyzickej aktivite?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotiť a nahrávať video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Táto aplikácia bude môcť fotiť a nahrávať videá iba vtedy, keď ju budete používať"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotiť a nahrávať videá?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Táto aplikácia môže požadovať nepretržitý prístup k foteniu a nahrávaniu videí, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Chcete aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; zmeniť prístup k fotoaparátu?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Táto aplikácia požaduje nepretržitý prístup k foteniu a nahrávaniu videí, aj keď ju nepoužívate. "<annotation id="link">"Povolíte ho v nastaveniach."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"Ovládané povolenia"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> má prístup k polohe"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Vaša organizácia povoľuje aplikácii <xliff:g id="APP_NAME">%1$s</xliff:g> prístup k vašej polohe"</string>
@@ -583,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"Pre aplikácie a služby. Keď je toto nastavenie vypnuté a zavoláte na tiesňovú linku, údaje mikrofónu sa môžu stále zdieľať."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Zobraziť aplikácie a služby, ktoré majú prístup k polohe"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Zobrazovať prístup k schránke"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Zobrazovať správu, keď sa aplikácie získajú pristup k textu, obrázkom alebo inému obsahu, ktorý ste skopírovali"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Zobrazovať správu, keď aplikácie získajú pristup k textu, obrázkom alebo inému obsahu, ktorý ste skopírovali"</string>
<string name="show_password_title" msgid="2877269286984684659">"Zobrazovať heslá"</string>
<string name="show_password_summary" msgid="1110166488865981610">"Pri písaní nakrátko zobrazovať zadávané znaky"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"V tejto aplikácii bolo uvedené, že môže zdieľať údaje o polohe s tretími stranami"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Zdieľanie údajov a poloha"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Odkiaľ pochádzajú informácie o zdieľaní údajov"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Vývojár poskytol výrobcovi tohto zariadenia informácie, ako táto aplikácia zdieľa údaje. Priebežne môže dané informácie aktualizovať."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Vývojár poskytol v sekcii "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" informácie o tom, ako táto aplikácia zdieľa údaje. Priebežne môže dané informácie aktualizovať."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Aplikácia môže zdieľať údaje o polohe na účely:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Zdieľanie údajov sa líši"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Zabezpečenie údajov"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Môžu sa zdieľať údaje o polohe"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"V tejto aplikácii je uvedené, že môže zdieľať údaje o polohe s tretími stranami"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Tento odkaz sa nedá otvoriť"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Aktualizácie zdieľania údajov o polohe"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Skontrolujte aplikácie, ktoré zmenili spôsob zdieľania údajov o vašej polohe"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Tieto aplikácie zmenili spôsob zdieľania údajov o vašej polohe. Možno ich v minulosti nezdieľali alebo ich teraz zdieľajú na účely reklamy a marketingu."</string>
diff --git a/PermissionController/res/values-sl-v33/strings.xml b/PermissionController/res/values-sl-v33/strings.xml
index 6d250edb4..6bc0748fb 100644
--- a/PermissionController/res/values-sl-v33/strings.xml
+++ b/PermissionController/res/values-sl-v33/strings.xml
@@ -20,7 +20,7 @@
<string name="role_sms_request_description" msgid="1506966389698625395">"Ta aplikacija vam bo lahko pošiljala obvestila ter bo imela dostop do fotoaparata, stikov, datotek, mikrofona, telefona in sporočil SMS."</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"Aplikacije s tem dovoljenjem lahko dostopajo do vseh datotek v tej napravi."</string>
<string name="work_policy_title" msgid="832967780713677409">"Podatki o službenem pravilniku"</string>
- <string name="work_policy_summary" msgid="3886113358084963931">"Nastavitve upravlja skrbnik za IT"</string>
+ <string name="work_policy_summary" msgid="3886113358084963931">"Nastavitve upravlja skrbnik za IT."</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Razširi in prikaži seznam"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"Strni seznam in skrij nastavitve"</string>
<string name="safety_center_entry_group_content_description" msgid="7048420958214443333">"Seznam. <xliff:g id="ENTRY_TITLE">%1$s</xliff:g>. <xliff:g id="ENTRY_SUMMARY">%2$s</xliff:g>"</string>
@@ -40,7 +40,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Stikalo. <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g>. <xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Preklop"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Odpri"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Pregled nastavitev"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Preglejte nastavitve"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Nastavitve"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Informacije"</string>
</resources>
diff --git a/PermissionController/res/values-sl-v34/strings.xml b/PermissionController/res/values-sl-v34/strings.xml
index a616b355e..18afff3d1 100644
--- a/PermissionController/res/values-sl-v34/strings.xml
+++ b/PermissionController/res/values-sl-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Varnost in zasebnost"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Kontrolniki"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Upravljajte dostop aplikacij do podatkov o zdravju"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Upravljajte dostop aplikacij do podatkov o zdravju."</string>
<string name="location_settings" msgid="8863940440881290182">"Dostop do lokacije"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Za aplikacije in storitve. Če je ta nastavitev izklopljena, bodo podatki mikrofona morda še vedno deljeni, ko pokličete številko za klic v sili."</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"Za aplikacije in storitve"</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"Za aplikacije in storitve."</string>
</resources>
diff --git a/PermissionController/res/values-sl/strings.xml b/PermissionController/res/values-sl/strings.xml
index 9b6cbf369..7a8487722 100644
--- a/PermissionController/res/values-sl/strings.xml
+++ b/PermissionController/res/values-sl/strings.xml
@@ -40,7 +40,7 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ne dovoli kljub temu"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Opusti"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> od <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Ali dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; izvesti to dejanje: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; izvesti to dejanje: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; vedno dovoliti to dejanje: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Samo med uporabo aplikacije"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Vedno"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Vedno dovoli"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dovoli samo med uporabo aplik."</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Dovoli samo med uporabo aplikacije"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Ne dovoli"</string>
<string name="loading" msgid="4789365003890741082">"Nalaganje …"</string>
<string name="all_permissions" msgid="6911125611996872522">"Vsa dovoljenja"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Nazadnje odprto: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Če dovolite upravljanje vseh datotek, lahko ta aplikacija dostopa do vseh datotek, ki so v skupni shrambi v tej napravi ali povezanih napravah za shranjevanje, ter jih ureja in briše. Aplikacija lahko do datotek dostopa brez vaše vednosti."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Ali tej aplikaciji dovolite dostop do datotek, ki so v napravi ali drugih povezanih napravah za shranjevanje, ter njihovo spreminjanje in brisanje? Ta aplikacija lahko do datotek dostopa brez vaše vednosti."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije s tem dovoljenjem imajo te možnosti: <xliff:g id="DESCRIPTION">%1$s</xliff:g>."</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacije s tem dovoljenjem lahko izvedejo to dejanje: <xliff:g id="DESCRIPTION">%1$s</xliff:g>."</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Aplikacije s tem dovoljenjem lahko dostopajo do podatkov o vaši telesni dejavnosti, na primer hoji, kolesarjenju, vožnji, številu korakov itd."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Aplikacije s tem dovoljenjem lahko dostopajo do koledarja."</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Aplikacije s tem dovoljenjem lahko berejo dnevnik klicev v telefonu in zapisujejo vanj."</string>
@@ -455,48 +455,75 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Prikaz zaznavanja sprožilca za pomočnika"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Prikaz ikone v vrstici stanja, ko z mikrofonom aktivirate glasovnega pomočnika"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do fotografij in predstavnosti v napravi?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do fotografij in predstavnosti v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do stikov?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do stikov v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do lokacije te naprave?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do lokacije naprave &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacija bo imela dostop do lokacije samo, ko aplikacijo uporabljate"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do lokacije te naprave?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do lokacije naprave &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ta aplikacija bo morda želela imeti stalen dostop do vaše lokacije, tudi ko aplikacije ne boste uporabljali. "<annotation id="link">"Omogočite v nastavitvah."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Želite spremeniti dostop do lokacije za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Želite spremeniti dostop do lokacije za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ta aplikacija želi imeti stalen dostop do vaše lokacije, tudi ko aplikacije ne uporabljate. "<annotation id="link">"Omogočite v nastavitvah."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Ali apl. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovolite iskanje naprav v bližini, povezovanje z njimi in določanje njihove rel. lokacije?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Žel. apl. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti isk. napr. v bliž., pov. z njimi in določ. rel. lok. v napr. &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Ali aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovolite iskanje naprav v bližini, povezovanje z njimi in določanje njihove rel. lokacije? "<annotation id="link">"Omogočite v nastavitvah."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Ali želite aplikaciji <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> omogočiti dostop do natančne lokacije namesto približne?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Želite dostop do lokacije za aplikacijo <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; spremeniti iz približnega v natančnega?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do približne lokacije te naprave?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do približne lokacije naprave &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Natančna"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Približna"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do koledarja?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do koledarja v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; pošiljanje in ogled sporočil SMS?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti pošiljanje in ogled sporočil SMS v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do fotografij, predstavnosti in datotek v svoji napravi?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Želite aplik. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do fotografij, predstavnosti in datotek v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do &lt;b&gt;fotografij, videoposnetkov, glasbe in zvočnih datotek&lt;/b&gt; v tej napravi?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do &lt;b&gt;fotografij, videoposnetkov, glasbe, zvočnih datotek in drugih datotek&lt;/b&gt; v tej napravi?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do glasbe in zvočnih datotek v tej napravi?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do glasbe in zvočnih datotek v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do fotografij in videoposnetkov v tej napravi?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do fotografij in videoposnetkov v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do več fotografij in videoposnetkov v tej napravi?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do več fotografij in videoposnetkov v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snemanje zvoka?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti snemanje zvoka v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacija bo lahko snemala zvok le med vašo uporabo aplikacije."</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti snemanje zvoka?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti snemanje zvoka v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ta aplikacija bo morda želela vseskozi snemati zvok, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Želite spremeniti dostop do mikrofona za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Želite spremeniti dostop do mikrofona za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ta aplikacija želi vseskozi snemati zvok, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dostop do svoje telesne dejavnosti?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do telesne dejavnosti v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Dovolite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotografiranje in snemanje videoposnetkov?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti snemanje fotografij in videoposnetkov v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacija bo lahko snemala fotografije in videoposnetke le med vašo uporabo aplikacije."</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti fotografiranje in snemanje videoposnetkov?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti snemanje fotografij in videoposnetkov v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ta aplikacija bo morda želela vseskozi snemati fotografije in videoposnetke, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Želite spremeniti dostop do fotoaparata za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Želite spremeniti dostop do fotoaparata za aplikacijo &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ta aplikacija želi vseskozi snemati fotografije in videoposnetke, tudi ko aplikacije ne uporabljate. "<annotation id="link">"To omogočite v nastavitvah."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do dnevnikov telefonskih klicev v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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_device_aware_phone" msgid="4389610977195521813">"Želite aplik. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti opravljanje in upravljanje telefonskih klicev v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do podatkov tipal o vitalnih znakih v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti dostop do podatkov tipal o vitalnih znakih v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Č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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Žel. apl. &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; še napr. dov. dost. do pod. tip. tel. funkc., ko je v upor.?"</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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; dovoliti pošiljanje obvestil v napravi &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Zunanje upravljana dovoljenja"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ima dostop do lokacije"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Vaša organizacija aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> dovoljuje dostop do vaše lokacije."</string>
@@ -579,7 +606,7 @@
<string name="privacy_controls_title" msgid="7605929972256835199">"Nastavitve zasebnosti"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Dostop do fotoaparata"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Dostop do mikrofona"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Za aplikacije in storitve"</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Za aplikacije in storitve."</string>
<string name="mic_toggle_description" msgid="9163104307990677157">"Za aplikacije in storitve. Če je ta nastavitev izklopljena, bodo podatki mikrofona morda še vedno deljeni, ko pokličete številko za klic v sili."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Oglejte si aplikacije in storitve, ki imajo dostop do lokacije."</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Pokaži dostop do odložišča"</string>
@@ -589,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ta aplikacija navaja, da bo lokacijske podatke morda delila s tretjimi osebami."</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Deljenje podatkov in lokacija"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Vir informacij o deljenju podatkov"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Razvijalec je z informacijami o tem, kako ta aplikacija deli podatke, seznanil proizvajalca naprave. Razvijalec bo morda te informacije občasno posodobil."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Razvijalec je z informacijami o tem, kako ta aplikacija deli podatke, seznanil trgovino z aplikacijami "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Razvijalec bo morda te informacije občasno posodobil."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ta aplikacija lahko deli lokacijske podatke za:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Načini deljenja podatkov se med seboj razlikujejo"</string>
@@ -606,10 +634,8 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Varnost podatkov"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Lokacijski podatki so morda deljeni z drugimi"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ta aplikacija navaja, da bo vaše lokacijske podatke morda delila s tretjimi osebami."</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Te povezave ni mogoče odpreti"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Posodobitve deljenja podatkov o lokaciji"</string>
- <string name="data_sharing_updates_summary" msgid="764113985772233889">"Pregled aplikacij s spremembami v načinu deljenja vaših lokacijskih podatkov"</string>
+ <string name="data_sharing_updates_summary" msgid="764113985772233889">"Pregled aplikacij s spremembami v načinu deljenja vaših lokacijskih podatkov."</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Te aplikacije so spremenile način deljenja vaših lokacijskih podatkov. Prej jih morda sploh niso delile ali pa jih zdaj delijo za namene oglaševanja ali trženja."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Razvijalci teh aplikacij so trgovino z aplikacijami seznanili z informacijami o svojih postopkih deljenja podatkov. Te informacije bodo občasno morda posodobljene.\n\nPostopki deljenja podatkov se lahko razlikujejo glede na različico aplikacije, njeno uporabo, regijo ali vašo starost."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Preberite več o deljenju podatkov."</string>
diff --git a/PermissionController/res/values-sq-v33/strings.xml b/PermissionController/res/values-sq-v33/strings.xml
index 6bbdb8b5b..bbe8e9a89 100644
--- a/PermissionController/res/values-sq-v33/strings.xml
+++ b/PermissionController/res/values-sq-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Sinjalizime të tjera"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Sinjalizime të shpërfillura"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Zgjero dhe shiko një sinjalizim tjetër}other{Zgjero dhe shiko # sinjalizime të tjera}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Sinjalizim. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Veprimi përfundoi"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Shiko cilësimet që mund të shtojnë mbrojtjen e pajisjes sate"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Cilësimet e shpejta të sigurisë dhe të privatësisë"</string>
diff --git a/PermissionController/res/values-sq/strings.xml b/PermissionController/res/values-sq/strings.xml
index 806dd572e..6923dc515 100644
--- a/PermissionController/res/values-sq/strings.xml
+++ b/PermissionController/res/values-sq/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Mos lejo gjithsesi"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Hiqe"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> nga <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; që të <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Të lejohet gjithmonë &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; që <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të kryejë këtë veprim: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Të lejohet gjithmonë &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të kryejë këtë veprim: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Vetëm gjatë përdorimit të aplikacionit"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Gjithmonë"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Mos lejo dhe mos pyet përsëri"</string>
@@ -195,8 +195,8 @@
<string name="approximate_image_description" msgid="938803699637069884">"Vendndodhja e përafërt"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Përdor vendndodhjen e saktë"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kur është joaktive vendndodhja e saktë, aplikacionet mund të qasen te vendndodhja jote e përafërt"</string>
- <string name="app_permission_title" msgid="2090897901051370711">"Leje për te <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Qasja te <xliff:g id="PERM">%1$s</xliff:g> për këtë aplikacion"</string>
+ <string name="app_permission_title" msgid="2090897901051370711">"Leje për te \"<xliff:g id="PERM">%1$s</xliff:g>\""</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Qasja te \"<xliff:g id="PERM">%1$s</xliff:g>\" për këtë aplikacion"</string>
<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>
@@ -211,7 +211,7 @@
<string name="auto_revoke_open_app_message" msgid="8075556291711205039">"Nëse dëshiron t\'i lejosh përsëri lejet, hap aplikacionin."</string>
<string name="auto_revoke_disabled" msgid="8697684442991567188">"Heqja automatike aktualisht është çaktivizuar për këtë aplikacion."</string>
<string name="auto_revocable_permissions_none" msgid="8334929619113991466">"Aktualisht nuk janë dhënë leje të revokueshme automatikisht"</string>
- <string name="auto_revocable_permissions_one" msgid="5299112369449458176">"Leja për \"<xliff:g id="PERM">%1$s</xliff:g>\" do të hiqet."</string>
+ <string name="auto_revocable_permissions_one" msgid="5299112369449458176">"Leja për te \"<xliff:g id="PERM">%1$s</xliff:g>\" do të hiqet."</string>
<string name="auto_revocable_permissions_two" msgid="4874067408752041716">"Lejet <xliff:g id="PERM_0">%1$s</xliff:g> dhe <xliff:g id="PERM_1">%2$s</xliff:g> do të hiqen."</string>
<string name="auto_revocable_permissions_many" msgid="1521807896206032992">"Lejet që do të hiqen: <xliff:g id="PERMS">%1$s</xliff:g>."</string>
<string name="auto_manage_title" msgid="7693181026874842935">"Menaxho automatikisht lejet"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Hapur së fundi më <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Nëse lejon menaxhimin e të gjithë skedarëve, ky aplikacion mund të ketë qasje, modifikojë dhe fshijë çdo skedar në hapësirën ruajtëse të përbashkët në këtë pajisje ose pajisjet me hapësirë ruajtëse të lidhur. Aplikacioni mund të ketë qasje te skedarët pa të pyetur."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Të lejohet që ky aplikacion të qaset, modifikojë dhe fshijë skedarët në pajisje ose në çdo pajisje me hapësirë ruajtëse të lidhur? Ky aplikacion mund të ketë qasje te skedarët pa të pyetur."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacioneve me këtë leje u lejohet <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Aplikacioneve me këtë leje u lejohet ky veprim: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Aplikacionet me këtë leje mund të kenë qasje tek aktiviteti yt fizik, si: ecja në këmbë, me biçikletë, me makinë, numërimi i hapave etj."</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Aplikacionet me këtë leje mund të kenë qasje te kalendari yt"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Aplikacionet me këtë leje mund të lexojnë dhe të shkruajnë në evidencën e telefonatave të telefonit"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Shfaq zbulimin e aktivizimit të asistentit"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Shfaq ikonën në shiritin e statusit kur përdoret mikrofoni për të aktivizuar asistentin me zë"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te fotografitë dhe media në pajisjen tënde?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te kontaktet e tua?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te vendndodhja e kësaj pajisjeje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Aplikacioni do të ketë qasje te vendndodhja vetëm kur po e përdor aplikacionin"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te vendndodhja e kësaj pajisjeje?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ky aplikacion mund të dëshirojë të ketë qasje në vendndodhjen tënde gjatë gjithë kohës, edhe kur nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Do ta ndryshosh qasjen për vendndodhjen për &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ky aplikacion dëshiron të ketë qasje në vendndodhjen tënde gjatë gjithë kohës, edhe kur nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të gjejë, lidhet dhe përcaktojë pozicionin relativ të pajisjeve në afërsi?"</string>
- <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të gjejë, lidhet dhe përcaktojë pozicionin relativ të pajisjeve në afërsi? "<annotation id="link">"Lejoje te cilësimet."</annotation></string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të gjejë, të lidhet dhe të përcaktojë pozicionin relativ të pajisjeve në afërsi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Të lejohet &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të gjejë, të lidhet dhe të përcaktojë pozicionin relativ të pajisjeve në afërsi? "<annotation id="link">"Lejoje te cilësimet."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Të ndryshohet qasja që ka <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> te vendndodhja nga \"e përafërt\" në \"e saktë\"?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te vendndodhja e përafërt e kësaj pajisjeje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"E saktë"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"E përafërt"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te kalendari yt?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të dërgojë dhe të shikojë mesazhet SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te fotografitë, media dhe skedarët në pajisjen tënde?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te &lt;b&gt;fotografitë, videot, muzika dhe audioja&lt;/b&gt; në këtë pajisje?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Të lejohet që &lt;b&amp;gt<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te &lt;b&gt;fotografitë, videot, muzika, audioja e të tjera&lt;/b&gt; në pajisje?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te muzika dhe te audioja në këtë pajisje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje te fotografitë dhe videot në këtë pajisje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të qaset te më shumë fotografi dhe video në pajisje?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të regjistrojë audio?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Aplikacioni do të mund të regjistrojë audion vetëm kur ti po e përdor aplikacionin"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të regjistrojë audio?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ky aplikacion mund të dëshirojë të regjistrojë audion gjatë gjithë kohës, edhe kur ti nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Të ndryshohet qasja për mikrofonin për &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ky aplikacion dëshiron të regjistrojë audion gjatë gjithë kohës, edhe kur ti nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të ketë qasje në aktivitetin tënd fizik?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të nxjerrë fotografi dhe të regjistrojë video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Aplikacioni do të mund të nxjerrë fotografi dhe të regjistrojë video vetëm kur ti po e përdor aplikacionin"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të nxjerrë fotografi dhe të regjistrojë video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ky aplikacion mund të dëshirojë të nxjerrë fotografi dhe video gjatë gjithë kohës, edhe kur ti nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Të ndryshohet qasja për kamerën për &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ky aplikacion dëshiron të nxjerrë fotografi dhe video gjatë gjithë kohës, edhe kur ti nuk po e përdor aplikacionin. "<annotation id="link">"Lejoje te cilësimet"</annotation>"."</string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Lejet e kontrolluara"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Lejet e kontrolluara"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ka qasje te vendndodhja"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Organizata jote lejon që <xliff:g id="APP_NAME">%1$s</xliff:g> të ketë qasje te vendndodhja jote"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Leje të tjera"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Lejet e përdorura nga sistemi"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Lejet e përdorura vetëm nga aplikacionet e sistemit."</string>
@@ -591,7 +643,8 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ky aplikacion deklaroi se mund të ndajë të dhënat e vendndodhjes me palë të treta"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Ndarja e të dhënave dhe vendndodhja"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Nga vijnë informacionet rreth ndarjes së të dhënave"</string>
- <string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Zhvilluesi i ofroi informacione "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" rreth mënyrës se si ky aplikacion ndan të dhënat. Zhvilluesi mund t\'i përditësojë këto informacione me kalimin e kohës."</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Zhvilluesi i ka dhënë informacione prodhuesit të kësaj pajisjeje rreth mënyrës se si ky aplikacion ndan të dhënat. Zhvilluesi mund t\'i përditësojë këto informacione me kalimin e kohës."</string>
+ <string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Zhvilluesi i ka dhënë informacione "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" rreth mënyrës se si ky aplikacion ndan të dhënat. Zhvilluesi mund t\'i përditësojë këto informacione me kalimin e kohës."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Apl. mund të ndajë të dhënat e vendndodhjes për:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Ndarja e të dhënave ndryshon"</string>
<string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"Veprimet me të dhënat mund të ndryshojnë bazuar në versionin e aplikacionit, përdorimin, rajonin dhe moshën tënde. "<annotation id="link">"Më shumë rreth ndarjes së të dhënave"</annotation></string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Siguria e të dhënave"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Të dhënat e vendndodhjes mund të ndahen"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ky aplikacion deklaroi se mund të ndajë të dhënat e vendndodhjes sate me palë të treta"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Kjo lidhje nuk mund të hapet"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Përditësime për ndarjen e të dhënave për vendndodhjen"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Shqyrto aplikacionet që ndryshuan mënyrën se si mund të ndajnë të dhënat e vendndodhjes sate"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Këto aplikacione kanë ndryshuar mënyrën se si mund të ndajnë të dhënat e vendndodhjes sate. Ato mund të mos i kenë ndarë më parë ose mund t\'i ndajnë tani për qëllime reklamimi dhe marketingu."</string>
diff --git a/PermissionController/res/values-sr-v33/strings.xml b/PermissionController/res/values-sr-v33/strings.xml
index c169467d3..1fe22cee5 100644
--- a/PermissionController/res/values-sr-v33/strings.xml
+++ b/PermissionController/res/values-sr-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Још обавештења"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Одбачена обавештења"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Проширите и видите још једно обавештење}one{Проширите и видите још # обавештење}few{Проширите и видите још # обавештења}other{Проширите и видите још # обавештења}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Обавештење. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Радња је довршена"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Проверите подешавања која могу да додају заштиту уређају"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Брза подешавања безбедности и приватности"</string>
diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml
index 689ad201d..e07131d77 100644
--- a/PermissionController/res/values-sr/strings.xml
+++ b/PermissionController/res/values-sr/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Увек дозволи све"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Изаберите слике и видео снимке"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Изаберите још"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Не бирај више"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Ништа више"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Ионако не дозволи"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Одбаци"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> од <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
@@ -108,7 +108,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
<string name="permission_access_always" msgid="1474641821883823446">"Дозволи увек"</string>
- <string name="permission_access_only_foreground" msgid="7801170728159326195">"Дозв. само док се апл. користи"</string>
+ <string name="permission_access_only_foreground" msgid="7801170728159326195">"Дозволи само док се апл. користи"</string>
<string name="permission_access_never" msgid="4647014230217936900">"Не дозволи"</string>
<string name="loading" msgid="4789365003890741082">"Учитава се…"</string>
<string name="all_permissions" msgid="6911125611996872522">"Све дозволе"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Последњи пут отворено: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ако омогућите управљање свим датотекама, ова апликација може да приступа свим датотекама у заједничком меморијском простору на овом уређају или повезаним уређајима за складиштење и да мења и брише те датотеке. Апликација може да приступа датотекама без питања."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Желите ли да дозволите да ова апликација приступа датотекама на уређају или свим повезаним уређајима за складиштење и да мења и брише те датотеке? Ова апликација може да приступа датотекама без питања."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Апликације са овом дозволом могу <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Апликације са том дозволом имају ове могућности: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Апликације са овом дозволом могу да приступају подацима о физичким активностима, попут ходања, вожње бицикла, вожње аутомобила, броја корака и друго"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Апликације са овом дозволом могу да приступају календару"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Апликације са овом дозволом могу да читају и додају ставке у евиденцију позива на телефону"</string>
@@ -397,7 +397,7 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и приступ дозволама за телефон, SMS поруке, контакте и календар."</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> ће добити дозволу за интеракцију са обавештењима и стримовање апликација на повезаном уређају."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Ова услуга дели слике, медијски садржај и обавештења са телефона на другим уређајима."</string>
- <string name="role_notes_label" msgid="7451627001058089536">"Подразумевана аплик за белешке"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"Подразумевана апл. за белешке"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Апликација за белешке"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Апликације које вам омогућавају да правите белешке на уређају"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"белешке"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Приказуј откривање активирања помоћника"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Приказује икону на статусној траци када се микрофон користи за активирање гласовног помоћника"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Желите ли да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа сликама и медијима на уређају?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа контактима?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа локацији овог уређаја?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Апликација ће имати приступ локацији само док користите апликацију"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа локацији овог уређаја?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ова апликација можда жели да приступа локацији све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Желите ли да промените приступ локацији за апликацију &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ова апликација жели да приступа локацији све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Дозвољавате да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; проналази уређаје у близини, повезује се с њима и одређује им релативан положај?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Дозвољавате да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; проналази уређаје у близини, повезује се с њима и одређује им релативан положај? "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Желите ли да промените приступ апликације <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> из приближне локације на прецизну?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа приближној локацији овог уређаја?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Прецизна"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Приближна"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа календару?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; шаље и прегледа SMS-ове?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа сликама, медијским и другим фајловима на уређају?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Приступ &lt;b&gt;сликама, видеу, музици и звуку&lt;/b&gt; на уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Приступ сликама, видеу, музици, звуку и другом на уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Дозвољавате ли приступ музици и звуку на овом уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Дозвољавате ли приступ сликама и видеу на овом уређају за &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Дозвољавате ли да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа и другим сликама и видео снимцима на овом уређају?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима звук?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Апликација ће моћи да снима звук само док користите апликацију"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима звук?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ова апликација можда жели да снима звук све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Желите да промените приступ микрофону за апликацију &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ова апликација жели да снима звук све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Желите ли да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа физичким активностима?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима слике и видео снимке?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Апликација ће моћи да снима слике и видео снимке само док користите апликацију"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима слике и видео снимке?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ова апликација можда жели да снима слике и видео снимке све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Желите да промените приступ камери за апликацију &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ова апликација жели да снима слике и видео снимке све време, чак и када не користите апликацију. "<annotation id="link">"Дозволите у подешавањима."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа евиденцијама позива на телефону?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; упућује позиве и управља њима?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Желите да дозволите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; приступа подацима сензора о виталним функцијама?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Да бисте дозволили овој апликацији да све време приступа подацима сензора за тело, чак и када не користите апликацију, "<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="auto_granted_permissions" msgid="6009452264824455892">"Контролисане дозволе"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Желите да дозволите да вам &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; шаље обавештења?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Контролисане дозволе"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> има приступ локацији"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Организација дозвољава да <xliff:g id="APP_NAME">%1$s</xliff:g> приступа локацији"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Друге дозволе"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Дозволе које користи систем"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Дозволе које користе само системске апликације."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Ова апликација наводи да може да дели податке са трећим странама"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Дељење података и локација"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Одакле информације о дељењу података потичу"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Програмер је навео информације произвођачу овог уређаја о томе како ова апликација дели податке. Програмер може временом да ажурира ове податке."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Програмер је навео информације о томе како ова апликација дели податке за:"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Програмер може временом да ажурира ове податке."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ова апликација може да дели податке о локацији за:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Дељење података варира"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Безбедност података"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Подаци о локацији могу да се деле"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Ова апликација наводи да може да дели податке о локацији са трећим странама"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Не можемо да отворимо овај линк"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Ажурирања дељења података за локацију"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Прегледајте апликације које су промениле начин на који могу да деле податке о локацији"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Апликације су промениле начин на који могу да деле податке о локацији. Можда их нису делиле раније или их сада деле у сврхе оглашавања или маркетинга."</string>
diff --git a/PermissionController/res/values-sv-v33/strings.xml b/PermissionController/res/values-sv-v33/strings.xml
index cc2c40543..e661efeb0 100644
--- a/PermissionController/res/values-sv-v33/strings.xml
+++ b/PermissionController/res/values-sv-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Fler varningar"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Ignorerade varningar"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Utöka för att visa en varning till}other{Utöka för att visa # varningar till}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Varning. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Åtgärd slutförd"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Kontrollera inställningar som kan skydda enheten"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Snabbinställningar för säkerhet och integritet"</string>
diff --git a/PermissionController/res/values-sv-v34/strings.xml b/PermissionController/res/values-sv-v34/strings.xml
index aa81c12ec..09e204e2e 100644
--- a/PermissionController/res/values-sv-v34/strings.xml
+++ b/PermissionController/res/values-sv-v34/strings.xml
@@ -20,7 +20,7 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Säkerhet och integritet"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Kontroller"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Hantera appens åtkomst till din hälsodata"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Hantera appars åtkomst till din hälsodata"</string>
<string name="location_settings" msgid="8863940440881290182">"Platsåtkomst"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"För appar och tjänster. Om inställningen är inaktiverad kan mikrofondata fortfarande delas när du ringer ett nödnummer"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"För appar och tjänster"</string>
diff --git a/PermissionController/res/values-sv/strings.xml b/PermissionController/res/values-sv/strings.xml
index c5039d891..ba2c5379e 100644
--- a/PermissionController/res/values-sv/strings.xml
+++ b/PermissionController/res/values-sv/strings.xml
@@ -113,7 +113,7 @@
<string name="loading" msgid="4789365003890741082">"Läser in …"</string>
<string name="all_permissions" msgid="6911125611996872522">"Alla behörigheter"</string>
<string name="other_permissions" msgid="2901186127193849594">"Andra appbehörigheter"</string>
- <string name="permission_request_title" msgid="8790310151025020126">"Begäran om behörighet"</string>
+ <string name="permission_request_title" msgid="8790310151025020126">"Behörighetsbegäran"</string>
<string name="wear_not_allowed_dlg_title" msgid="1429467891296932713">"Android Wear"</string>
<string name="wear_not_allowed_dlg_text" msgid="512340555334769098">"Åtgärder för att installera/avinstallera stöds inte på Wear."</string>
<string name="permission_review_title_template_install" msgid="1284337937156289081">"Välj vad du vill ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till"</string>
@@ -399,7 +399,7 @@
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Den här tjänsten delar dina foton, videor och aviseringar på telefonen med andra enheter."</string>
<string name="role_notes_label" msgid="7451627001058089536">"Standardapp för anteckningar"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"Anteckningsapp"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"Appar som låter dig ta anteckningar på enheten"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"Appar som låter dig göra anteckningar på enheten"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"anteckningar"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Nuvarande standardapp"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Fråga inte igen"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Visa när enheten lyssnar efter ord som aktiverar assistenten"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Visa en ikon i statusfältet när mikrofonen används för att aktivera röstassistenten"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomstbehörighet till foton och media på enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till dina kontakter?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till enhetens plats?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Appen får endast åtkomst till din plats när du använder den"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till enhetens plats?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Appen kanske vill få åtkomst till din plats hela tiden, även när du inte använder den. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Vill du ändra platsåtkomsten för &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Appen vill få åtkomst till din plats hela tiden, även när du inte använder den. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Vill du tillåta att &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kan hitta, ansluta till och fastställa relativ position för enheter i närheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Vill du tillåta att &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kan hitta, ansluta till och fastställa relativ position för enheter i närheten? "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Vill du ändra platsåtkomsten för <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> från ungefärlig till exakt?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till enhetens ungefärliga plats?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Exakt"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Ungefärlig"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till din kalender?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att skicka och visa sms?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till foton, mediefiler och andra filer på enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till &lt;b&gt;foton, videor, musik och ljud&lt;/b&gt; på enheten?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till &lt;b&gt;foton, videor, musik, ljud och andra filer&lt;/b&gt; på enheten?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till musik och ljud på enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till foton och videor på enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till fler foton och videor på enheten?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att spela in ljud?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Appen kan bara spela in ljud medan du använder den"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att spela in ljud?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Appen kanske vill spela in ljud hela tiden, även när du inte använder appen. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Vill du ändra mikrofonåtkomsten för &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Appen vill ha behörighet att spela in ljud hela tiden, även när du inte använder appen. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; åtkomst till data om fysisk aktivitet?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att ta bilder och spela in video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Appen kan bara ta bilder och spela in video medan du använder den"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att ta bilder och spela in video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Appen kanske vill ta bilder och spela in videor hela tiden, även när du inte använder appen. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Vill du ändra kameraåtkomsten för &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Appen vill ha behörighet att ta bilder och spela in videor hela tiden, även när du inte använder appen. "<annotation id="link">"Tillåt i inställningarna."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501"><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="auto_granted_permissions" msgid="6009452264824455892">"Styrda behörigheter"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Styrda behörigheter"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> har platsåtkomst"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Din organisation tillåter att <xliff:g id="APP_NAME">%1$s</xliff:g> får åtkomst till din plats"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Andra behörigheter"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Behörighet som används av systemet"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Behörigheter som bara används av systemappar."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Appen har angett att den kan dela platsdata med tredje part"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Datadelning och plats"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Härifrån kommer informationen om datadelning"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Utvecklaren har gett enhetens tillverkare information om hur appen delar data. Utvecklaren kan uppdatera den här informationen med tiden."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Utvecklaren har angett information om hur appen delar data i "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>". Utvecklaren kan uppdatera den här informationen med tiden."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Appen kan dela platsdata för följande:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Datadelningen varierar"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Datasäkerhet"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Platsdata kan delas"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Appen har angett att den kan dela din platsdata med tredje part"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Det gick inte att öppna den här länken"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Uppdatering av datadelning för plats"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Granska appar som har ändrat hur de kan dela din platsdata"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Dessa appar har ändrat hur de kan dela din platsdata. De kanske inte har delat datan tidigare eller så delas den nu i annons- och marknadsföringssyfte."</string>
diff --git a/PermissionController/res/values-sw-v33/strings.xml b/PermissionController/res/values-sw-v33/strings.xml
index 818d596a4..db02c110b 100644
--- a/PermissionController/res/values-sw-v33/strings.xml
+++ b/PermissionController/res/values-sw-v33/strings.xml
@@ -19,7 +19,7 @@
<string name="role_dialer_request_description" msgid="6188305064871543419">"Programu hii itaruhusiwa kukutumia Arifa na itapewa uwezo wa kufikia Kamera, Anwani, Maikrofoni, Simu na SMS kwenye kifaa chako"</string>
<string name="role_sms_request_description" msgid="1506966389698625395">"Programu hii itaruhusiwa kukutumia Arifa na itapewa uwezo wa kufikia Kamera, Anwani, Faili, Maikrofoni, Simu na SMS kwenye kifaa chako"</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"Programu zenye ruhusa hii zinaweza kufikia faili zote kwenye kifaa hiki"</string>
- <string name="work_policy_title" msgid="832967780713677409">"Maelezo ya sera yako ya kazini"</string>
+ <string name="work_policy_title" msgid="832967780713677409">"Maelezo ya sera ya kazini"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"Mipangilio inayodhibitiwa na msimamizi wako wa TEHAMA"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"Panua na uonyeshe orodha"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"Kunja orodha na ufiche mipangilio"</string>
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Arifa zaidi"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Arifa zilizoondolewa"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Panua na uangalie arifa moja zaidi}other{Panua na uangalie arifa # zaidi}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Tahadhari. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Kitendo kimekamilika"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Angalia mipangilio inayoweza kuongeza usalama wa kifaa chako"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Mipangilio ya haraka ya usalama na faragha"</string>
diff --git a/PermissionController/res/values-sw-v34/strings.xml b/PermissionController/res/values-sw-v34/strings.xml
index c4107efea..be6f2f72b 100644
--- a/PermissionController/res/values-sw-v34/strings.xml
+++ b/PermissionController/res/values-sw-v34/strings.xml
@@ -20,8 +20,8 @@
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Usalama na faragha"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Vidhibiti"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Kudhibiti uwezo wa programu wa kufikia data ya afya"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Dhibiti uwezo wa programu wa kufikia data ya afya"</string>
<string name="location_settings" msgid="8863940440881290182">"Uwezo wa kufikia mahali"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Kwenye programu na huduma. Mipangilio hii ikizimwa, huenda data ya maikrofoni ikaendelea kushirikiwa unapopiga nambari ya dharura"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Kwenye programu na huduma. Mipangilio hii ikizimwa, data ya maikrofoni bado inaweza ikashirikiwa unapopiga nambari ya dharura"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Kwenye programu na huduma"</string>
</resources>
diff --git a/PermissionController/res/values-sw/strings.xml b/PermissionController/res/values-sw/strings.xml
index ded75a6e1..2d5721307 100644
--- a/PermissionController/res/values-sw/strings.xml
+++ b/PermissionController/res/values-sw/strings.xml
@@ -221,7 +221,7 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"Programu zisizotumika"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"Programu isipotumika kwa miezi kadhaa:\n\n• Ruhusa huondolewa ili kulinda data yako \n• Arifa husimamishwa ili kuokoa betri\n• Faili za muda huondolewa ili upate nafasi\n\nIli uidhinishe ruhusa na arifa tena, fungua programu."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Programu isipotumika kwa mwezi mmoja:\n\n• Ruhusa huondolewa ili kulinda data yako\n• Faili za muda huondolewa ili upate nafasi\n\nIli uidhinishe ruhusa tena, fungua programu."</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Zilifunguliwa mara ya mwisho zaidi ya mwezi # uliopita}other{Zilifunguliwa mara ya mwisho zaidi ya miezi # iliyopita}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Zilifunguliwa mwisho zaidi ya mwezi # uliopita}other{Zilifunguliwa mwisho zaidi ya miezi # iliyopita}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"Ilifunguliwa mara ya mwisho tarehe <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"Ilifunguliwa mara ya mwisho <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Ukiruhusu udhibiti wa faili zote, programu hii inaweza kufikia, kubadilisha na kufuta faili zozote zilizo katika hifadhi kwenye kifaa hiki au vifaa vilivyounganishwa vya kuhifadhi. Programu inaweza kufikia faili bila kukuomba ruhusa."</string>
@@ -347,8 +347,8 @@
<string name="accessibility_service_dialog_title_multiple" msgid="5527879210683548175">"Programu <xliff:g id="NUM_SERVICES">%s</xliff:g> za ufikivu zina idhini kamili ya kufikia kifaa chako"</string>
<string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"<xliff:g id="SERVICE_NAME">%s</xliff:g> inaweza kuona skrini, vitendo na maudhui unayoweka, kutekeleza vitendo na kudhibiti onyesho."</string>
<string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"Programu hizi zinaweza kuona skrini, vitendo na maudhui unayoweka, kutekeleza vitendo na kudhibiti onyesho."</string>
- <string name="role_assistant_label" msgid="4727586018198208128">"Programu msingi dijitali ya usaidizi"</string>
- <string name="role_assistant_short_label" msgid="3369003713187703399">"Programu dijitali ya usaidizi"</string>
+ <string name="role_assistant_label" msgid="4727586018198208128">"Programu msingi ya usaidizi wa kidijitali"</string>
+ <string name="role_assistant_short_label" msgid="3369003713187703399">"Programu saidizi ya kidijitali"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"Programu za usaidizi zinaweza kukusaidia kulingana na maelezo kutoka skrini unayotazama. Baadhi ya programu zinaweza kutumia huduma za kifungua programu na kuweka data kwa kutamka ili kukupa usaidizi wa pamoja."</string>
<string name="role_browser_label" msgid="2877796144554070207">"Programu kuu ya kivinjari"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"Programu ya kivinjari"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Onyesha utambuzi wa kuwashwa/kuzimwa kwa mratibu"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Onyesha aikoni kwenye sehemu ya kuonyesha hali wakati maikrofoni inatumika kuwasha kipengele cha maagizo ya sauti"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha na maudhui kwenye kifaa chako?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie anwani zako?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie mahali kilipo kifaa hiki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Programu itafikia data ya mahali ulipo unapoitumia tu"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie mahali kilipo kifaa hiki?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Huenda programu hii ikataka kufikia maelezo ya mahali ulipo kila wakati, hata wakati huitumii."<annotation id="link">"Iruhusu katika mipangilio."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Ungependa kubadilisha ruhusa za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; za kufikia maelezo ya mahali?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Programu hii inataka kufikia maelezo ya mahali ulipo kila wakati, hata wakati huitumii."<annotation id="link">"Iruhusu katika mipangilio."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itafute, iunganishe kwenye na ibaini mahali vilipo vifaa vilivyo karibu?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itafute, iunganishe kwenye na ibaini mahali vilipo vifaa vilivyo karibu? "<annotation id="link">"Ruhusu katika mipangilio."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Ungependa kubadilisha ufikiaji wa maelezo ya mahali kwenye <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> kutoka eneo lililokadiriwa utumie eneo mahususi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie mahali palipokadiriwa kilipo kifaa hiki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Mahususi"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Palipokadiriwa"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie kalenda yako?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itume na ione ujumbe wa SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Ungependa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha, maudhui na faili kwenye kifaa chako?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie &lt;b&gt;picha, video, muziki na sauti&lt;/b&gt; kwenye kifaa hiki?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie &lt;b&gt;picha, video, muziki, sauti na faili zingine&lt;/b&gt; kwenye kifaa hiki?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie muziki na sauti kwenye kifaa hiki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha na video kwenye kifaa hiki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie picha na video zaidi kwenye kifaa hiki?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kurekodi sauti?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Programu itaweza kurekodi sauti unapoitumia tu"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; irekodi sauti?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Huenda programu hii ikataka kurekodi sauti kila wakati, hata wakati huitumii."<annotation id="link">"Ruhusu katika mipangilio."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Ungependa kubadilisha ruhusa za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; za kufikia maikrofoni?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Programu hii inataka kurekodi sauti kila wakati, hata wakati huitumii."<annotation id="link">"Ruhusu katika mipangilio."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ifikie shughuli zako za kimwili?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; kupiga picha na kurekodi video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Programu itaweza kupiga picha na kurekodi video unapoitumia tu"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ipige picha na kurekodi video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Huenda programu hii ikataka kupiga picha na kurekodi video kila wakati, hata wakati huitumii."<annotation id="link">"Ruhusu katika mipangilio."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Ungependa kubadilisha ruhusa za &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; za kufikia kamera?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Programu hii inataka kupiga picha na kurekodi video kila wakati, hata wakati huitumii."<annotation id="link">"Ruhusu katika mipangilio."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<string name="permgroupupgraderequestdetail_sensors" msgid="6651914048792092835">"Programu hii inataka kufikia data ya vitambuzi ya 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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Ili uruhusu programu hii ifikie data ya vitambuzi vya 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 vya 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="auto_granted_permissions" msgid="6009452264824455892">"Ruhusa zinazodhibitiwa"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Ruhusa zinazodhibitiwa"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ina idhini ya kufikia maelezo ya mahali kilipo kifaa"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Shirika lako limeruhusu <xliff:g id="APP_NAME">%1$s</xliff:g> kufikia maelezo ya mahali kilipo kifaa chako"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Ruhusa nyinginezo"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Ruhusa zinazotumiwa na mfumo"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Ruhusa zinazotumiwa tu na programu za mfumo."</string>
@@ -572,9 +624,9 @@
<string name="media_confirm_dialog_message_q_to_s_aural_deny" msgid="6832087393653561911">"Programu hii haiwezi kutumia toleo jipya zaidi la Android. Iwapo programu hii haitaweza kufikia faili za muziki na sauti, haitaruhusiwa pia kufikia picha na video."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"Programu hii haiwezi kutumia toleo jipya zaidi la Android. Iwapo programu hii itaweza kufikia picha na video, itaruhusiwa pia kufikia muziki na faili za sauti."</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"Programu hii haiwezi kutumia toleo jipya zaidi la Android. Iwapo programu hii haitaweza kufikia faili za muziki na sauti, haitaruhusiwa pia kufikia picha na video."</string>
- <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Kagua programu yenye ufikiaji wa ruhusa ya kubainisha mahali chinichini"</string>
+ <string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Kagua programu yenye ufikiaji wa mahali chinichini"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> inaweza kufikia mahali ulipo kila wakati, hata kama programu imefungwa"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Kagua programu yenye ufikiaji wa ruhusa ya kubainisha mahali chinichini"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Kagua programu yenye ufikiaji wa mahali chinichini"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Programu hii inaweza kufikia data ya mahali ulipo kila wakati, hata kama imefungwa.\n\nBaadhi ya programu za usalama na dharura zinahitaji ufikiaji wa data ya mahali ulipo chinichini ili kufanya kazi ipasavyo."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Ruhusa ya ufikiaji imebadilishwa"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Angalia matumizi ya hivi karibuni ya maelezo ya mahali"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Maelezo ya programu yanasema kuwa inaweza kushiriki data na kampuni za wengine"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Kushiriki data na mahali"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Maelezo ya kushiriki data yanakotokea"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Msanidi programu ametoa maelezo kwa mtengenezaji wa kifaa hiki kuhusu jinsi programu hii inavyoshiriki data. Msanidi programu anaweza kusasisha maelezo haya kadiri muda unavyosonga."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Wasanidi programu wametoa maelezo kwenye "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" kuhusu jinsi programu hii inavyoshiriki data. Msanidi programu anaweza kusasisha maelezo haya kadiri muda unavyosonga."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Programu hii inaweza kushiriki data ya mahali ili:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Kanuni za kushiriki data hutofautiana"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Usalama wa data"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Data ya mahali inaweza kushirikiwa"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Programu hii ilitaja kuwa inaweza kushiriki data yako ya mahali na washirika wengine"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Huwezi kufungua kiungo hiki"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Masasisho ya kushiriki data ya mahali"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Kagua programu zilizobadilisha jinsi zinavyoweza kushiriki data ya mahali ulipo"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Programu hizi zimebadilisha jinsi zinavyoweza kushiriki data ya mahali ulipo. Huenda zilikuwa haziishiriki hapo awali au sasa zinaweza kuishiriki kwa madhumuni ya utangazaji au uuzaji."</string>
diff --git a/PermissionController/res/values-ta-v33/strings.xml b/PermissionController/res/values-ta-v33/strings.xml
index cdb8a15f5..41b6d0923 100644
--- a/PermissionController/res/values-ta-v33/strings.xml
+++ b/PermissionController/res/values-ta-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"கூடுதல் விழிப்பூட்டல்கள்"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"நிராகரிக்கப்பட்ட விழிப்பூட்டல்கள்"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{விரிவாக்கி மேலும் ஒரு விழிப்பூட்டலைப் பாருங்கள்}other{விரிவாக்கி மேலும் # விழிப்பூட்டல்களைப் பாருங்கள்}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"விழிப்பூட்டும். <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"செயல் நிறைவடைந்தது"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"உங்கள் சாதனத்திற்குப் பாதுகாப்பைச் சேர்க்கக்கூடிய அமைப்புகளைப் பாருங்கள்"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"பாதுகாப்பு &amp; தனியுரிமை விரைவு அமைப்புகள்"</string>
diff --git a/PermissionController/res/values-ta/strings.xml b/PermissionController/res/values-ta/strings.xml
index d62e0d481..748725235 100644
--- a/PermissionController/res/values-ta/strings.xml
+++ b/PermissionController/res/values-ta/strings.xml
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"கடைசியாகத் திறந்தது: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"அனைத்து ஃபைல்களையும் நிர்வகிப்பதற்கு அனுமதி வழங்கினால் இந்தச் சாதனத்தின் பொதுவான சேமிப்பகத்திலோ இணைக்கப்பட்டுள்ள சேமிப்பகச் சாதனங்களிலோ உள்ள ஃபைல்களை அணுகவும் நீக்கவும் அவற்றில் மாற்றங்களைச் செய்யவும் இந்த ஆப்ஸால் முடியும். உங்களிடம் கேட்காமலேயே ஃபைல்களை ஆப்ஸ் அணுகக்கூடும்."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"இந்தச் சாதனத்திலோ இணைக்கப்பட்டுள்ள சேமிப்பகச் சாதனங்களிலோ உள்ள ஃபைல்களை அணுகவும் நீக்கவும் அவற்றில் மாற்றங்களைச் செய்யவும் இந்த ஆப்ஸை அனுமதிக்கவா? உங்களிடம் கேட்காமலேயே ஃபைல்களை இந்த ஆப்ஸ் அணுகக்கூடும்."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"இந்த அனுமதியைக் கொண்டுள்ள ஆப்ஸானது <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"இந்த அனுமதியைக் கொண்டுள்ள ஆப்ஸால் இதைச் செய்ய முடியும்: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"இந்த அனுமதியைக் கொண்டுள்ள ஆப்ஸால் நடத்தல், சைக்கிள் ஓட்டுதல், வாகனம் ஓட்டுதல், படிகளில் ஏறி இறங்குதல் மற்றும் பல உடல்ரீதியான செயல்பாடுகளை அணுக இயலும்"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"இந்த அனுமதியைக் கொண்டுள்ள ஆப்ஸால் உங்கள் கேலெண்டரை அணுக இயலும்"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"இந்த அனுமதியைக் கொண்டுள்ள ஆப்ஸ் மொபைல் அழைப்புப் பதிவைப் படிக்கும், எழுதும்"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"அசிஸ்டண்ட் இயக்கப்படுவதைக் கண்டறியும் ஐகானைக் காட்டு"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"குரல் உதவியை இயக்க மைக்ரோஃபோனைப் பயன்படுத்தும்போது நிலைப் பட்டியில் ஐகானைக் காட்டு"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"இந்தச் சாதனத்திலுள்ள படங்களையும் மீடியாவையும் அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"தொடர்புகளை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"இந்தச் சாதன இருப்பிடத்தை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"இந்த ஆப்ஸை நீங்கள் உபயோகிக்கும்போது மட்டுமே இருப்பிடத்தை அணுகும்"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"இந்தச் சாதனத்தின் இருப்பிடத்தை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"இந்த ஆப்ஸை நீங்கள் பயன்படுத்தாதபோதும்கூட உங்கள் இருப்பிடத்தை எந்நேரமும் அணுக இது விரும்பக்கூடும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸிற்கு இருப்பிட அணுகலை மாற்றவா?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"இந்த ஆப்ஸை நீங்கள் பயன்படுத்தாதபோதும்கூட உங்கள் இருப்பிடத்தை எந்நேரமும் அணுக இது விரும்பக்கூடும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"அருகிலுள்ள சாதனங்களைக் கண்டறியவும் அவற்றுடன் இணையவும் அவற்றின் தூரத்தைத் தீர்மானிக்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"அருகிலுள்ள சாதனங்களைக் கண்டறியவும் அவற்றுடன் இணையவும் அவற்றின் தூரத்தைத் தீர்மானிக்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா? "<annotation id="link">"அமைப்புகளில் அனுமதி."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> ஆப்ஸின் இருப்பிட அணுகலைத் தோராயத்திலிருந்து துல்லியத்திற்கு மாற்றவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"இந்தச் சாதனத்தின் தோராயமான இருப்பிடத்தை அணுக &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"துல்லியமானது"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"தோராயமானது"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"கேலெண்டரை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"மெசேஜ்களை அனுப்பவும், பார்க்கவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"உங்கள் சாதனத்திலுள்ள படங்கள், மீடியா, ஃபைல்கள் ஆகியவற்றை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"சாதனத்திலுள்ள &lt;b&gt;படங்கள், வீடியோக்கள், இசை &amp; ஆடியோவுக்கான&lt;/b&gt; அணுகலை &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு வழங்கவா?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"சாதனத்திலுள்ள &lt;b&gt;படம், வீடியோ, இசை, ஆடியோ &amp; பிற ஃபைல்களின்&lt;/b&gt; அணுகலை &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு வழங்கவா?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"இந்தச் சாதனத்திலுள்ள இசை மற்றும் ஆடியோவுக்கான அணுகலை &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு வழங்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"இந்தச் சாதனத்திலுள்ள படங்கள் மற்றும் வீடியோக்களுக்கான அணுகலை &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு வழங்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"இந்தச் சாதனத்திலுள்ள கூடுதல் படங்கள் மற்றும் வீடியோக்களுக்கான அணுகலை &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கு வழங்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ஆடியோ ரெக்கார்டு செய்ய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"இந்த ஆப்ஸை நீங்கள் உபயோகிக்கும்போது மட்டுமே ஆடியோ ரெக்கார்டு செய்யும்"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ஆடியோ ரெக்கார்டு செய்ய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"இந்த ஆப்ஸை உபயோகிக்காத போதும்கூட எந்நேரமும் ஆடியோ ரெக்கார்டு செய்ய அனுமதி கேட்கக்கூடும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கான மைக்ரோஃபோன் அணுகலை மாற்றவா?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"இந்த ஆப்ஸை உபயோகிக்காத போதும்கூட எந்நேரமும் ஆடியோ ரெக்கார்டு செய்ய அனுமதி கேட்கிறது. "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"உடல் செயல்பாட்டைக் கண்காணிக்க &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"படங்கள் எடுக்கவும் வீடியோ ரெக்கார்டு செய்யவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"இந்த ஆப்ஸை நீங்கள் உபயோகிக்கும்போது மட்டுமே படங்கள் எடுக்கும், வீடியோ ரெக்கார்டு செய்யும்"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"படங்கள் எடுக்கவும் வீடியோ ரெக்கார்டு செய்யவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"இந்த ஆப்ஸை உபயோகிக்காத போதும்கூட எந்நேரமும் படங்கள் எடுக்கவும் வீடியோ ரெக்கார்டு செய்யவும் அனுமதி கேட்கக்கூடும். "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸுக்கான கேமரா அணுகலை மாற்றவா?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"இந்த ஆப்ஸை உபயோகிக்காத போதும்கூட எந்நேரமும் படங்கள் எடுக்கவும் வீடியோ ரெக்கார்டு செய்யவும் அனுமதி கேட்கிறது. "<annotation id="link">"அமைப்புகளில் அனுமதிக்கவும்."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"உங்கள் மொபைல் அழைப்புப் பதிவுகளை அணுக, &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"மொபைல் அழைப்புகள் செய்யவும், அவற்றை நிர்வகிக்கவும், &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"உங்கள் உடலியக்கக் குறிகள் பற்றிய சென்சார் தரவை அணுகுவதற்கு &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"இந்த ஆப்ஸ் எல்லா நேரங்களிலும் உடல் சென்சார் தரவை அணுக (நீங்கள் ஆப்ஸைப் பயன்படுத்தாதபோதும்) "<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="auto_granted_permissions" msgid="6009452264824455892">"கட்டுப்படுத்தப்பட்ட அனுமதிகள்"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"உங்களுக்கு அறிவிப்புகளை அனுப்ப &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"கட்டுப்படுத்தப்பட்ட அனுமதிகள்"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு இருப்பிட அணுகல் உள்ளது"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"உங்கள் இருப்பிடத்தை <xliff:g id="APP_NAME">%1$s</xliff:g> அணுக உங்கள் நிறுவனம் அனுமதிக்கிறது"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"பிற அனுமதிகள்"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"சிஸ்டத்தால் பயன்படுத்தப்படும் அனுமதி"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"சிஸ்டம் ஆப்ஸால் மட்டுமே பயன்படுத்தப்படும் அனுமதிகள்."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"மூன்றாம் தரப்பினருடன் இருப்பிடத் தரவைப் பகிரலாம் என இந்த ஆப்ஸ் குறிப்பிடுகிறது"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"தரவுப் பகிர்வு மற்றும் இருப்பிடம்"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"தரவுப் பகிர்வு குறித்த தகவல்கள் எங்கிருந்து பெறப்படுகின்றன?"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"இந்த ஆப்ஸ் எப்படித் தரவைப் பகிர்கிறது என்பது குறித்த தகவல்களை டெவலப்பர் இந்தச் சாதனத்தின் உற்பத்தியாளருக்கு வழங்கியுள்ளார். டெவெலப்பர் காலப்போக்கில் இந்தத் தகவல்களைப் புதுப்பிக்கக்கூடும்."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"இந்த ஆப்ஸ் எப்படித் தரவைப் பகிர்கிறது என்பது குறித்த தகவல்களை டெவெலப்பர் "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" என்பதற்கு வழங்கியுள்ளார். டெவெலப்பர் காலப்போக்கில் இந்தத் தகவல்களை மாற்றக்கூடும்."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ஆப்ஸ் இவற்றுக்காக இருப்பிடத் தரவைப் பகிரக்கூடும்:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"தரவுப் பகிர்வு வேறுபடுகிறது"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"தரவுப் பாதுகாப்பு"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"இருப்பிடத் தரவு பகிரப்படலாம்"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"இந்த ஆப்ஸில் குறிப்பிட்டுள்ளபடி மூன்றாம் தரப்பினருடன் இருப்பிடத் தரவை இது பகிரலாம்"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"இந்த இணைப்பைத் திறக்க முடியவில்லை"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"இருப்பிடத்திற்கான தரவுப் பகிர்வு குறித்த அறிவிப்புகள்"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"உங்கள் இருப்பிடத் தரவைப் பகிரும் விதத்தை மாற்றிய ஆப்ஸ் எவை எனப் பாருங்கள்"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"உங்கள் இருப்பிடத் தரவைப் பகிரும் விதத்தை இந்த ஆப்ஸ் மாற்றியுள்ளன. இதற்குமுன் அவற்றைப் பகிராமல் இருந்திருக்கலாம் அல்லது விளம்பரப்படுத்தல், மார்கெட்டிங் போன்ற நோக்கங்களுக்காக இப்போது பகிரக்கூடும்."</string>
diff --git a/PermissionController/res/values-te/strings.xml b/PermissionController/res/values-te/strings.xml
index 562b6f4cd..e53922c97 100644
--- a/PermissionController/res/values-te/strings.xml
+++ b/PermissionController/res/values-te/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"ఏదేమైనా అనుమతించవద్దు"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"విస్మరించు"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> యొక్క <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని <xliff:g id="ACTION">%2$s</xliff:g> చేయడానికి అనుమతించాలా?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"<xliff:g id="ACTION">%2$s</xliff:g> చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను ఎల్లప్పుడూ అనుమతించాలా?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‌ను ఈ చర్య చేయడానికి అనుమతించాలా? - <xliff:g id="ACTION">%2$s</xliff:g>"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"ఈ చర్యను చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‌ను ఎల్లప్పుడూ అనుమతించాలా? - <xliff:g id="ACTION">%2$s</xliff:g>"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"ఎల్లప్పుడూ"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"అనుమతించవద్దు, మళ్లీ అడగవద్దు"</string>
@@ -194,9 +194,9 @@
<string name="precise_image_description" msgid="6349638632303619872">"ఖచ్చితమైన లొకేషన్"</string>
<string name="approximate_image_description" msgid="938803699637069884">"సుమారు లొకేషన్"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"ఖచ్చితమైన లొకేషన్‌ను ఉపయోగించండి"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"ఖచ్చితమైన లొకేషన్ ఆఫ్‌లో ఉన్నప్పుడు, యాప్‌లు మీ సుమారు లొకేషన్‌ను యాక్సెస్ చేయగలగవచ్చు"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"ఖచ్చితమైన లొకేషన్ అనే సెట్టింగ్ ఆఫ్‌లో ఉన్నప్పుడు, యాప్‌లు మీ సుమారు లొకేషన్‌ను యాక్సెస్ చేయగలవు"</string>
<string name="app_permission_title" msgid="2090897901051370711">"\'<xliff:g id="PERM">%1$s</xliff:g>\' అనుమతి"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"ఈ యాప్ కోసం \'<xliff:g id="PERM">%1$s</xliff:g>\' యాక్సెస్"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"ఈ యాప్ కోసం \'<xliff:g id="PERM">%1$s</xliff:g>\' యాక్సెస్‌ను ఇవ్వాలా? వద్దా"</string>
<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>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"చివరిగా తెరిచినది <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"మీరు అన్ని ఫైళ్ల మేనేజ్‌మెంట్‌కు అనుమతిస్తే,ఈ పరికరంలో లేదా కనెక్ట్ చేయబడిన స్టోరేజ్ పరికరాలలో ఉమ్మడి స్టోరేజ్‌లోని ఏ ఫైళ్లను అయినా ఈ యాప్ యాక్సెస్ చేయగలదు, సవరించగలదు, లేదా తొలగించగలదు. యాప్ మీ అనుమతి తీసుకోకుండానే ఫైళ్లను యాక్సెస్ చేయవచ్చు."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"ఈ పరికరంలో లేదా ఏవైనా కనెక్ట్ చేయబడిన స్టోరేజ్ పరికరాలలో ఫైళ్లను యాక్సెస్ చేయడానికి, ఎడిట్ చేయడానికి, లేదా తొలగించడానికి ఈ యాప్‌నకు అనుమతి ఇవ్వాలా? ఈ యాప్ మీ అనుమతి తీసుకోకుండానే ఫైళ్లను యాక్సెస్ చేయవచ్చు."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"ఈ యాప్‌ల‌కు ఈ అనుమ‌తి ఇస్తుంది- <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"ఈ అనుమ‌తి ఉన్న యాప్‌లు ఇది చేయగలవు- <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"వాకింగ్, బైకింగ్, సైక్లింగ్, అడుగులను లెక్కించడం మొదలైన శారీరక శ్రమను, ఇంకా మరిన్నింటిని ఈ అనుమతి ఉన్న యాప్‌లు యాక్సెస్ చేయగలవు"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"ఈ అనుమతి ఉన్న యాప్‌లు మీ క్యాలెండర్‌ను యాక్సెస్ చేయగలవు"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"ఈ అనుమతి ఉన్న యాప్‍‌లు ఫోన్ కాల్ లాగ్‌ను చదవగలుగుతాయి, దానిలో రాయగలుగుతాయి"</string>
@@ -250,7 +250,7 @@
<string name="allowed_foreground_header" msgid="6845655788447833353">"ఉపయోగించేటప్పుడు మాత్రమే అనుమతి ఇవ్వాలి"</string>
<string name="allowed_storage_scoped" msgid="5383645873719086975">"మీడియాకు మాత్రమే యాక్సెస్ అనుమతించబడినవి"</string>
<string name="allowed_storage_full" msgid="5356699280625693530">"ఫైల్స్ అన్నింటినీ మేనేజ్ చేసేందుకు అనుమతించబడినవి"</string>
- <string name="ask_header" msgid="2633816846459944376">"ప్రతిసారి అడుగు"</string>
+ <string name="ask_header" msgid="2633816846459944376">"ప్రతిసారి అడగాలి"</string>
<string name="denied_header" msgid="903209608358177654">"అనుమతించబడలేదు"</string>
<string name="storage_footer_hyperlink_text" msgid="8873343987957834810">"అన్ని ఫైళ్లను యాక్సెస్ చేయగల మరిన్ని యాప్‌లను చూడండి"</string>
<string name="days" msgid="609563020985571393">"{count,plural, =1{1 రోజు}other{# రోజులు}}"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Assistant ట్రిగ్గర్ గుర్తింపును చూపించడం"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"వాయిస్ అసిస్టెంట్‌ను యాక్టివేట్ చేయడానికి మైక్రోఫోన్‌ను ఉపయోగించినప్పుడు, స్టేటస్ బార్‌లో చిహ్నాన్ని చూపు"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"మీ పరికరంలో ఫోటోలు, మీడియా ఫైళ్లను యాక్సెస్ చేయగలిగేలా &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"మీ కాంటాక్ట్‌లను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"ఈ పరికర లొకేషన్‌ను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"మీరు యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే లొకేషన్‌కు యాప్ యాక్సెస్ కలిగి ఉంటుంది"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"ఈ పరికర లొకేషన్‌ను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ఈ యాప్‌నకు మీ లొకేషన్ యాక్సెస్ అన్ని సమయాలలో, అంటే యాప్‌ను ఉపయోగించనప్పుడు కూడా, అవసరం ఉండవచ్చు. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; కోసం లొకేష‌న్‌ యాక్సెస్‌ను మార్చాలా?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"మీరు యాప్ ఉపయోగించనప్పుడు కూడా ఈ యాప్ మీ లొకేష‌న్‌ను ఎప్పటికప్పుడు యాక్సెస్ చేయాల‌ని అనుకుంటోంది."<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"సమీప పరికరాల సంబంధిత స్థానాన్ని కనుగొనడానికి, కనెక్ట్ చేయడానికి అలాగే నిర్ణయించడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"సమీప పరికరాల సంబంధిత స్థానాన్ని కనుగొనడానికి, కనెక్ట్ చేయడానికి అలాగే నిర్ణయించడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా? "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>కు సంబంధించిన లొకేషన్ యాక్సెస్‌ను సుమారు నుండి ఖచ్చితమైనదిగా మార్చాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"ఈ పరికరానికి సంబంధించి సుమారుగా ఉన్న లొకేషన్‌ను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"ఖచ్చితమైన"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"సుమారుగా"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"మీ క్యాలెండర్‌ని యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS మెసేజ్‌లు పంపడం, చూడటం చేయగలిగేలా &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"మీ పరికరంలోని ఫోటోలు, మీడియా, ఫైళ్లను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‌ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"ఈ పరికరంలో &lt;b&gt;ఫోటోలు, వీడియోలు, మ్యూజిక్, ఆడియో&lt;/b&gt;ను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"ఈపరికరంలో &lt;b&gt;ఫోటోలు, వీడియోలు, మ్యూజిక్, ఆడియో, ఇతర ఫైళ్ల&lt;/b&gt; యాక్సెస్‌కు &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"ఈ పరికరంలో మ్యూజిక్‌ను, ఆడియోను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‌ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"ఈ పరికరంలో ఫోటోలను, వీడియోలను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‌ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"ఈ పరికరంలోని మరిన్ని ఫోటోలను, వీడియోలను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; యాప్‌ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"ఆడియోను రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"మీరు యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే ఈ యాప్, ఆడియోను రికార్డ్ చేయగలుగుతుంది"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"ఆడియోను రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"మీరు యాప్ ఉపయోగించనప్పుడు కూడా ఈ యాప్ ఎల్లప్పుడూ ఆడియోను రికార్డ్ చేయాలనుకోవచ్చు. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; కోసం మైక్రోఫోన్ యాక్సెస్‌ను మార్చాలా?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"మీరు యాప్ ఉపయోగించనప్పుడు కూడా ఈ యాప్ ఎల్లప్పుడూ ఆడియోను రికార్డ్ చేయాలనుకుంటోంది. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"మీ భౌతిక యాక్టివిటీని యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"ఫోటోలు తీయడానికి, వీడియో రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"మీరు యాప్‌ను ఉపయోగిస్తున్నప్పుడు మాత్రమే ఈ యాప్, ఫోటోలను తీయగలుగుతుంది, వీడియోను రికార్డ్ చేయగలుగుతుంది"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"ఫోటోలు తీయడానికి, వీడియోను రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"మీరు యాప్ ఉపయోగించనప్పుడు కూడా ఈ యాప్ ఎల్లప్పుడూ ఫోటోలను తీయాలనుకోవచ్చు, వీడియోను రికార్డ్ చేయాలనుకోవచ్చు. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; కోసం కెమెరా యాక్సెస్‌ను మార్చాలా?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"మీరు యాప్ ఉపయోగించనప్పుడు కూడా ఈ యాప్ ఎల్లప్పుడూ ఫోటోలను తీయాలనుకుంటోంది, వీడియోను రికార్డ్ చేయాలనుకుంటోంది. "<annotation id="link">"సెట్టింగ్‌లలో అనుమతించండి."</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"మీ ఫోన్ కాల్ లాగ్‌లను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"ఫోన్‌ కాల్స్‌ చేయడానికి, మేనేజ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"మీ అత్యంత కీలకమైన గుర్తుల గురించి సెన్సార్ డేటాను యాక్సెస్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"మీరు యాప్‌ను ఉపయోగించనప్పుడు కూడా, శరీర సెన్సార్ డేటాను ఎల్లప్పుడూ యాక్సెస్ చేయడానికి ఈ యాప్‌ను అనుమతించడానికి, "<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"మీకు నోటిఫికేషన్‌లను పంపడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ను అనుమతించాలా?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"నియంత్రణలో ఉన్న అనుమతులు"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g>‌కు లొకేషన్ యాక్సెస్ ఉంది"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"మీ సంస్థ, మీ లొకేషన్‌ను యాక్సెస్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g>‌నకు అనుమతి ఇస్తుంది"</string>
@@ -572,7 +626,7 @@
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"ఈ యాప్ Android తాజా వెర్షన్‌కు సపోర్ట్ ఇవ్వదు. ఈ యాప్ మ్యూజిక్, ఆడియో ఫైల్స్‌ను యాక్సెస్ చేయలేకపోతే, ఫోటోలు, వీడియోలను యాక్సెస్ చేయడానికి కూడా ఇది అనుమతించబడదు."</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"Review app with background location access"</string>
<string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"<xliff:g id="APP_NAME">%s</xliff:g> can always access your location, even when the app is closed"</string>
- <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"బ్యాక్‌గ్రౌండ్ లొకేషన్‌కు యాక్సెస్‌ను కలిగి ఉన్న యాప్‌ను రివ్యూ చేయండి"</string>
+ <string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"బ్యాక్‌గ్రౌండ్ లొకేషన్‌కు యాక్సెస్‌ ఉన్న యాప్‌ను రివ్యూ చేయండి"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"ఈ యాప్ అది మూసివేసి ఉన్నప్పుడు కూడా, మీ లొకేషన్‌ను ఎల్లప్పుడూ యాక్సెస్ చేయగలదు.\n\nకొన్ని భద్రత, ఎమర్జెన్సీ యాప్‌లు ఉద్దేశించిన విధంగా పని చేయడానికి, వాటికి బ్యాక్‌గ్రౌండ్‌లో మీ లొకేషన్‌కు యాక్సెస్ అవసరం."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"యాక్సెస్‌ మార్చబడింది."</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"ఇటీవలి లొకేషన్‌ వినియోగాన్ని చూడండి"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"ఈ యాప్, అది లొకేషన్ డేటాను థర్డ్-పార్టీలతో షేర్ చేయవచ్చని పేర్కొంది"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"డేటా షేరింగ్ &amp; లొకేషన్"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"డేటా షేరింగ్‌కు సంబంధించిన సమాచారం ఎక్కడి నుంచి వస్తుంది"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"డెవలపర్ ఈ యాప్, డేటాను ఎలా షేర్ చేస్తుంది అనే సమాచారాన్ని పరికర తయారీదారుకు అందించారు. డెవలపర్ ఈ సమాచారాన్ని కాలానుగుణంగా అప్‌డేట్ చేయవచ్చు."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"ఈ యాప్, డేటాను ఎలా షేర్ చేస్తుంది అనే సమాచారాన్ని డెవలపర్ "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"‌కు అందించారు. డెవలపర్ ఈ సమాచారాన్ని కాలానుగుణంగా అప్‌డేట్ చేయవచ్చు."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"ఈ యాప్ లొకేషన్ డేటాను వీటి కోసం షేర్ చేయవచ్చు:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"డేటా షేరింగ్ మారుతూ ఉంటుంది"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"డేటా భద్రత"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"లొకేషన్ డేటా షేర్ చేయబడవచ్చు"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"ఈ యాప్ మీ లొకేషన్ డేటాను థర్డ్-పార్టీలతో షేర్ చేయవచ్చని పేర్కొంది"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"ఈ లింక్‌ను తెరవడం సాధ్యపడదు"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"లొకేషన్‌కు సంబంధించిన డేటా షేరింగ్ అప్‌డేట్‌లు"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"మీ లొకేషన్ డేటాను షేర్ చేసే విధానాన్ని మార్చిన యాప్‌లను రివ్యూ చేయండి"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ఈ యాప్‌లు మీ లొకేషన్ డేటాను షేర్ చేయగల విధానాన్ని మార్చాయి. అవి దీన్ని ఇంతకు ముందు షేర్ చేసి ఉండకపోవచ్చు, లేదా ఇప్పుడు అడ్వర్టయిజింగ్ లేదా మార్కెటింగ్ ప్రయోజనాల కోసం షేర్ చేయవచ్చు."</string>
diff --git a/PermissionController/res/values-th-v33/strings.xml b/PermissionController/res/values-th-v33/strings.xml
index 4cae29b03..1270c9c1c 100644
--- a/PermissionController/res/values-th-v33/strings.xml
+++ b/PermissionController/res/values-th-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"การแจ้งเตือนเพิ่มเติม"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"การแจ้งเตือนที่ปิดไป"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ขยายและดูการแจ้งเตือนอีก 1 รายการ}other{ขยายและดูการแจ้งเตือนอีก # รายการ}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"การแจ้งเตือน <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"การดำเนินการเสร็จสมบูรณ์"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"ตรวจสอบการตั้งค่าที่เพิ่มการปกป้องให้กับอุปกรณ์ได้"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"การตั้งค่าด่วนด้านความปลอดภัยและความเป็นส่วนตัว"</string>
diff --git a/PermissionController/res/values-th-v34/strings.xml b/PermissionController/res/values-th-v34/strings.xml
index 7380c49d2..8e6bae837 100644
--- a/PermissionController/res/values-th-v34/strings.xml
+++ b/PermissionController/res/values-th-v34/strings.xml
@@ -21,7 +21,7 @@
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"การควบคุม"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"จัดการสิทธิ์เข้าถึงข้อมูลสุขภาพของแอป"</string>
- <string name="location_settings" msgid="8863940440881290182">"การเข้าถึงตำแหน่ง"</string>
+ <string name="location_settings" msgid="8863940440881290182">"สิทธิ์เข้าถึงตำแหน่ง"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"สำหรับแอปและบริการ หากปิดการตั้งค่านี้ ระบบอาจยังคงแชร์ข้อมูลไมโครโฟนเมื่อคุณโทรหาหมายเลขฉุกเฉิน"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"สำหรับแอปและบริการ"</string>
</resources>
diff --git a/PermissionController/res/values-th/strings.xml b/PermissionController/res/values-th/strings.xml
index 4e0916510..5bcc3eaf9 100644
--- a/PermissionController/res/values-th/strings.xml
+++ b/PermissionController/res/values-th/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"อนุญาตทั้งหมดตลอดเวลา"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"เลือกรูปภาพและวิดีโอ"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"เลือกเพิ่มเติม"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"ไม่ต้องเลือกเพิ่มเติม"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"ไม่เลือกเพิ่มแล้ว"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"ยังคงไม่อนุญาต"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"ปิด"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> จาก <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> รายการ"</string>
@@ -397,9 +397,9 @@
<string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและได้รับสิทธิ์เข้าถึงโทรศัพท์, SMS, รายชื่อติดต่อ และปฏิทิน"</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"<xliff:g id="APP_NAME">%1$s</xliff:g> จะได้รับอนุญาตให้โต้ตอบกับการแจ้งเตือนและสตรีมแอปไปยังอุปกรณ์ที่เชื่อมต่อ"</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"บริการนี้แชร์รูปภาพ สื่อ และการแจ้งเตือนจากโทรศัพท์ของคุณไปยังอุปกรณ์อื่น"</string>
- <string name="role_notes_label" msgid="7451627001058089536">"แอปการจดบันทึกเริ่มต้น"</string>
- <string name="role_notes_short_label" msgid="8796604147546125285">"แอปการจดบันทึก"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"แอปที่ให้คุณจดบันทึกในอุปกรณ์ได้"</string>
+ <string name="role_notes_label" msgid="7451627001058089536">"แอปโน้ตเริ่มต้น"</string>
+ <string name="role_notes_short_label" msgid="8796604147546125285">"แอปโน้ต"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"แอปที่ให้คุณจดโน้ตในอุปกรณ์ได้"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"บันทึก"</string>
<string name="request_role_current_default" msgid="738722892438247184">"แอปเริ่มต้นปัจจุบัน"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"ไม่ต้องถามอีก"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"แสดงการตรวจหาตัวทริกเกอร์ผู้ช่วย"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"แสดงไอคอนในแถบสถานะเมื่อมีการใช้ไมโครโฟนเพื่อเปิดใช้งานผู้ช่วยสั่งการด้วยเสียง"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรูปภาพและสื่อในอุปกรณ์ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรายชื่อติดต่อไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงตำแหน่งของอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"แอปจะมีสิทธิ์เข้าถึงตำแหน่งในขณะที่คุณใช้แอปเท่านั้น"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงตำแหน่งของอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"แอปนี้อาจต้องการเข้าถึงตำแหน่งของคุณตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป โปรด"<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"เปลี่ยนการเข้าถึงตำแหน่งสำหรับ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"แอปนี้ต้องการเข้าถึงตำแหน่งของคุณตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป โปรด"<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ค้นหา เชื่อมต่อ และระบุตำแหน่งสัมพัทธ์ของอุปกรณ์ที่อยู่ใกล้เคียงไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ค้นหา เชื่อมต่อ และระบุตำแหน่งซึ่งสัมพันธ์กับอุปกรณ์ที่อยู่ใกล้เคียง "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"เปลี่ยนการเข้าถึงตำแหน่งของ <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> จากตำแหน่งโดยประมาณเป็นตำแหน่งที่แน่นอนไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงตำแหน่งโดยประมาณของอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"แน่นอน"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"โดยประมาณ"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงปฏิทินไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ส่งและดูข้อความ SMS ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรูปภาพ สื่อ และไฟล์ในอุปกรณ์ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึง&lt;b&gt;รูปภาพ วิดีโอ เพลง และเสียง&lt;/b&gt;ในอุปกรณ์นี้ไหม"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึง&lt;b&gt;รูปภาพ วิดีโอ เพลง เสียง และไฟล์อื่นๆ&lt;/b&gt; ในอุปกรณ์นี้ไหม"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงเพลงและเสียงในอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรูปภาพและวิดีโอในอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงรูปภาพและวิดีโอเพิ่มเติมในอุปกรณ์นี้ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; บันทึกเสียงไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"แอปจะบันทึกเสียงได้ในขณะที่คุณใช้แอปอยู่เท่านั้น"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; บันทึกเสียงไหม"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"แอปนี้อาจต้องการบันทึกเสียงตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"เปลี่ยนแปลงสิทธิ์เข้าถึงไมโครโฟนของ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"แอปนี้ต้องการบันทึกเสียงตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ถ่ายรูปและบันทึกวิดีโอไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"แอปจะถ่ายภาพและวิดีโอได้ในขณะที่คุณใช้แอปอยู่เท่านั้น"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ถ่ายภาพและวิดีโอไหม"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"แอปนี้อาจต้องการถ่ายภาพและวิดีโอตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"เปลี่ยนแปลงสิทธิ์เข้าถึงกล้องถ่ายรูปของ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"แอปนี้ต้องการถ่ายภาพและวิดีโอตลอดเวลา แม้ในขณะที่คุณไม่ได้ใช้แอป "<annotation id="link">"อนุญาตในการตั้งค่า"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงบันทึกการโทรในโทรศัพท์ไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; โทรและจัดการการโทรไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงข้อมูลเซ็นเซอร์เกี่ยวกับสัญญาณชีพไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"หากต้องการให้แอปนี้เข้าถึงข้อมูลเซ็นเซอร์ร่างกายได้ทุกเมื่อ แม้ว่าคุณจะไม่ได้ใช้งานแอปอยู่ "<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="auto_granted_permissions" msgid="6009452264824455892">"สิทธิ์ที่มีการควบคุม"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ส่งการแจ้งเตือนถึงคุณไหม"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"สิทธิ์ที่มีการควบคุม"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> มีสิทธิ์เข้าถึงตำแหน่ง"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"องค์กรของคุณอนุญาตให้ <xliff:g id="APP_NAME">%1$s</xliff:g> เข้าถึงตำแหน่ง"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"สิทธิ์อื่นๆ"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"สิทธิ์ที่ใช้โดยระบบ"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"สิทธิ์ที่ใช้โดยแอปพลิเคชันระบบเท่านั้น"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"แอปนี้ระบุว่าแอปอาจแชร์ข้อมูลตำแหน่งกับองค์กรบุคคลที่สามของแอป"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"การแชร์ข้อมูลและตำแหน่ง"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"แหล่งที่มาของรายละเอียดการแชร์ข้อมูล"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"นักพัฒนาแอปได้ให้รายละเอียดเกี่ยวกับวิธีที่แอปนี้แชร์ข้อมูลไว้กับผู้ผลิตอุปกรณ์นี้ โดยอาจอัปเดตข้อมูลนี้เมื่อเวลาผ่านไป"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"นักพัฒนาแอปได้ให้รายละเอียดเกี่ยวกับวิธีที่แอปนี้แชร์ข้อมูลไว้ใน "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" โดยอาจอัปเดตข้อมูลนี้เมื่อเวลาผ่านไป"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"แอปนี้อาจแชร์ข้อมูลตำแหน่งเพื่อ"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"การแชร์ข้อมูลแตกต่างกันไปตามปัจจัยต่างๆ"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ความปลอดภัยของข้อมูล"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"อาจมีการแชร์ข้อมูลตำแหน่ง"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"แอปนี้ระบุว่าอาจแชร์ข้อมูลตำแหน่งของคุณกับบุคคลที่สาม"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"เปิดลิงก์นี้ไม่ได้"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"การอัปเดตการแชร์ข้อมูลตำแหน่ง"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ตรวจสอบแอปที่เปลี่ยนแปลงวิธีที่อาจใช้แชร์ข้อมูลตำแหน่งของคุณ"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"แอปต่อไปนี้ได้เปลี่ยนแปลงวิธีที่แอปอาจแชร์ข้อมูลตำแหน่งของคุณ โดยที่แอปอาจไม่เคยแชร์มาก่อน หรืออาจแชร์ในตอนนี้เพื่อวัตถุประสงค์ในการโฆษณาหรือการตลาดก็ได้"</string>
diff --git a/PermissionController/res/values-tl-v33/strings.xml b/PermissionController/res/values-tl-v33/strings.xml
index 28ef796d1..0c23a30f7 100644
--- a/PermissionController/res/values-tl-v33/strings.xml
+++ b/PermissionController/res/values-tl-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Higit pang alerto"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Mga na-dismiss na alerto"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{I-expand at makakita ng isa pang alerto}one{I-expand at makakita ng # pang alerto}other{I-expand at makakita ng # pang alerto}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Alerto. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Tapos na ang pagkilos"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Tingnan ang mga setting na makakapagdagdag ng proteksyon sa iyong device"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Mga mabilisang setting ng seguridad at privacy"</string>
diff --git a/PermissionController/res/values-tl/strings.xml b/PermissionController/res/values-tl/strings.xml
index 2b9beebd3..2dc504408 100644
--- a/PermissionController/res/values-tl/strings.xml
+++ b/PermissionController/res/values-tl/strings.xml
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Gamitin ang eksaktong lokasyon"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kapag naka-off ang eksaktong lokasyon, puwedeng i-access ng mga app ang iyong tinatantyang lokasyon"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Pahintulot sa <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"access sa <xliff:g id="PERM">%1$s</xliff:g> para sa app na ito"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Access sa <xliff:g id="PERM">%1$s</xliff:g> para sa app na ito"</string>
<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>
@@ -398,7 +398,7 @@
<string name="role_app_streaming_description" msgid="7341638576226183992">"Papayagan ang <xliff:g id="APP_NAME">%1$s</xliff:g> na makipag-ugnayan sa iyong mga notification at i-stream ang iyong mga app sa nakakonektang device."</string>
<string name="role_companion_device_computer_description" msgid="416099879217066377">"Ibinabahagi ng serbisyong ito ang iyong mga larawan, media, at notification sa ibang device mula sa iyong telepono."</string>
<string name="role_notes_label" msgid="7451627001058089536">"Default na app sa pagtatala"</string>
- <string name="role_notes_short_label" msgid="8796604147546125285">"App sa pagtatala"</string>
+ <string name="role_notes_short_label" msgid="8796604147546125285">"Notes app"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Mga app na nagbibigay-daan sa iyong magtala sa device mo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"mga tala"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Kasalukuyang default"</string>
@@ -455,53 +455,78 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Ipakita ang pagtukoy ng trigger ng assistant"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Ipakita ang icon sa status bar kapag gumamit ng mikropono para i-activate ang voice assistant"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan at media sa iyong device?"</string>
+ <string name="permgrouprequest_device_aware_storage_isolated" msgid="5934218468708513375">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan at media sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong mga contact?"</string>
+ <string name="permgrouprequest_device_aware_contacts" msgid="2270563860206654757">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong mga contact sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_location" msgid="6990232580121067883">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang lokasyon ng device na ito?"</string>
+ <string name="permgrouprequest_device_aware_location" msgid="6641436550953715107">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang lokasyon ng &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt; mo?"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Magkakaroon lang ang app ng access sa lokasyon habang ginagamit mo ang app"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang lokasyon ng device na ito?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_location" msgid="7660465507029650527">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang lokasyon ng &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g> mo?"</string>
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Posibleng gustong i-access ng app na ito ang iyong lokasyon sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Baguhin ang access sa lokasyon para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_location" msgid="4528266408056426513">"Baguhin ang access sa lokasyon para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Gustong i-access ng app na ito ang iyong lokasyon sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
- <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na hanapin at tukuyin ang, at kumonekta sa relatibong posisyon ng mga kalapit na device?"</string>
+ <string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na maghanap, kumonekta sa, at tukuyin ang relatibong posisyon ng mga kalapit na device?"</string>
+ <string name="permgrouprequest_device_aware_nearby_devices" msgid="7919687165848885665">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na humanap, kumonekta, at tumukoy ng posisyon ng nearby device sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na hanapin at tukuyin ang, at kumonekta sa relatibong posisyon ng mga kalapit na device? "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Gawing eksakto ang access sa lokasyon ng <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> mula sa pagiging tinatantya?"</string>
+ <string name="permgrouprequest_device_aware_fineupgrade" msgid="3947134846432067176">"Gawing tumpak mula sa tinataya ang access sa lokasyon ng <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang tinatantyang lokasyon ng device na ito?"</string>
+ <string name="permgrouprequest_device_aware_coarselocation" msgid="9001956706241104626">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang tinatayang lokasyon ng &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;’s mo?"</string>
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Eksakto"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Tinatantya"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong kalendaryo?"</string>
+ <string name="permgrouprequest_device_aware_calendar" msgid="3103987548035171850">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong kalendaryo sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na magpadala at tumingin ng mga mensaheng SMS?"</string>
+ <string name="permgrouprequest_device_aware_sms" msgid="7212083972999874267">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na magpadala at tumingin ng mga SMS message sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan, media, at file sa iyong device?"</string>
+ <string name="permgrouprequest_device_aware_storage" msgid="872629037299467086">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan, media, at file sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang &lt;b&gt;mga larawan, video, musika, at audio&lt;/b&gt; sa device?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang &lt;b&gt;mga larawan, video, musika, audio, at iba pang file&lt;/b&gt; sa device?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang musika at audio sa device na ito?"</string>
+ <string name="permgrouprequest_device_aware_read_media_aural" msgid="3331524384339036668">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang musika at audio sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan at video sa device na ito?"</string>
+ <string name="permgrouprequest_device_aware_read_media_visual" msgid="5492319750632751551">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang mga larawan at video sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang higit pang larawan at video sa device na ito?"</string>
+ <string name="permgrouprequest_device_aware_more_photos" msgid="8946782319103584021">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-access ng higit pang larawan at video sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-record ng audio?"</string>
+ <string name="permgrouprequest_device_aware_microphone" msgid="1266843551173029370">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-record ng audio sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Makakapag-record lang ng audio ang app habang ginagamit mo ang app"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-record ng audio?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone" msgid="4990337225146130185">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-record ng audio sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Posibleng gusto ng app na ito na mag-record ng audio sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Baguhin ang access sa mikropono para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_microphone" msgid="222471025997100107">"Baguhin ang access sa mikropono para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Gusto ng app na ito na mag-record ng audio sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong pisikal na aktibidad?"</string>
+ <string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na i-access ang iyong pisikal na aktibidad sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na kumuha ng larawan at mag-record ng video?"</string>
+ <string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na kumuha ng mga larawan at mag-record ng video sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Makakakuha lang ng mga larawan at makakapag-precord lang ng video ang app habang ginagamit mo ang app"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na kumuha ng mga larawan at mag-record ng video?"</string>
+ <string name="permgroupbackgroundrequest_device_aware_camera" msgid="6718286540040964849">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na kumuha ng mga larawan at mag-record ng video sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Posibleng gusto ng app na ito na kumuha ng larawan at mag-record ng video sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa settings."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Baguhin ang access sa camera para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <string name="permgroupupgraderequest_device_aware_camera" msgid="4198765626608612156">"Baguhin ang access sa camera para sa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Gusto ng app na ito na kumuha ng mga larawn at mag-record ng video sa lahat ng oras, kahit na hindi mo ginagamit ang app. "<annotation id="link">"Payagan sa mga setting."</annotation></string>
<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_device_aware_calllog" msgid="735079772627778095">"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 sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</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_device_aware_phone" msgid="4389610977195521813">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na gumawa at mamahala ng mga tawag sa telepono sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</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="permgrouprequest_device_aware_sensors" msgid="1900598688488188225">"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 mga vital sign mo sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</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="permgroupbackgroundrequest_device_aware_sensors" msgid="7691308331448239716">"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 mga vital sign mo sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="permgroupupgraderequest_device_aware_sensors" msgid="3310667992344623159">"Payagan 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 sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; habang ginagamit ito?"</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="permgrouprequest_device_aware_notifications" msgid="7307588961166360244">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na magpadala sa iyo ng mga notification sa &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt; mo?"</string>
<string name="auto_granted_permissions" msgid="6009452264824455892">"Kontroladong pahintulot"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
- <skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
- <skip />
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"May access sa lokasyon ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Pinapayagan ng organisasyon mo ang <xliff:g id="APP_NAME">%1$s</xliff:g> na i-access ang iyong lokasyon"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Iba pang pahintulot"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Pahintulot na ginagamit ng system"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Mga pahintulot na mga application ng system lang ang gumagamit."</string>
@@ -591,6 +616,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Isinaad ng app na ito na puwede nitong ibahagi ang data ng lokasyon sa mga third party"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Pagbabahagi ng data at lokasyon"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Saan nanggagaling ang impormasyon sa pagbabahagi ng data"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Nagbigay ang developer ng impormasyon sa manufacturer ng device na ito tungkol sa kung paano nagbabahagi ng data ang app na ito. Posibleng i-update ng developer ang impormasyong ito sa pagtagal."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Nagbigay ang developer ng impormasyon sa "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" tungkol sa kung paano nagbabahagi ng data ang app na ito. Posibleng i-update ng developer ang impormasyong ito sa paglipas ng panahon."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Puwedeng magbahagi ng data ng lokasyon para sa:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Nag-iiba ang pagbabahagi ng data"</string>
@@ -608,8 +634,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Kaligtasan ng data"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Puwedeng ibahagi ang data ng lokasyon"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Isinaad ng app na ito na puwede nitong ibahagi ang iyong data ng lokasyon sa mga third party"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Hindi mabuksan ang link na ito"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Mga update sa pagbabahagi ng data para sa lokasyon"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Suriin ang mga app na nagbago ng paraan kung paano nila posibleng ibahagi ang iyong data ng lokasyon"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Binago ng mga app na ito ang paraan kung paano posibleng ibahagi ng mga ito ang iyong data ng lokasyon. Posibleng hindi pa nila ito ibinahagi noon, o ibinabahagi nila ito ngayon para sa mga layunin sa pag-advertise o marketing."</string>
diff --git a/PermissionController/res/values-tr-v33/strings.xml b/PermissionController/res/values-tr-v33/strings.xml
index ddb34d1f2..d6d2e4286 100644
--- a/PermissionController/res/values-tr-v33/strings.xml
+++ b/PermissionController/res/values-tr-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Diğer uyarılar"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Reddedilen uyarılar"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Genişletip bir uyarıyı daha görün}other{Genişletip # uyarıyı daha görün}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Uyarı. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"İşlem tamamlandı"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Cihazınızın korumasını artırabilecek ayarlara göz atın"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Güvenlik ve gizlilikle ilgili hızlı ayarlar"</string>
diff --git a/PermissionController/res/values-tr/strings.xml b/PermissionController/res/values-tr/strings.xml
index 7e0c01670..057379cf5 100644
--- a/PermissionController/res/values-tr/strings.xml
+++ b/PermissionController/res/values-tr/strings.xml
@@ -36,11 +36,11 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Tümüne her zaman izin ver"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Fotoğraf ve video seçin"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Daha fazla seçin"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Daha fazla seçme"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"Başka seçilmesin"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Yine de izin verme"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Kapat"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına <xliff:g id="ACTION">%2$s</xliff:g> için izin verilsin mi?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına <xliff:g id="ACTION">%2$s</xliff:g> izni verilsin mi?"</string>
<string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına <xliff:g id="ACTION">%2$s</xliff:g> için her zaman izin verilsin mi?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Sadece uygulama kullanılırken"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Her zaman"</string>
@@ -221,7 +221,7 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"Kullanılmayan uygulamalar"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"Uygulama birkaç ay kullanılmazsa:\n\n• Verilerinizi korumak için izinler kaldırılır\n• Pilden tasarruf etmek için bildirimler durdurulur\n• Yer açmak için geçici dosyalar kaldırılır\n\nİzinleri ve bildirimleri yeniden etkinleştirmek için uygulamayı açın."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Uygulama bir ay kullanılmazsa:\n\n• Verilerinizi korumak için izinler kaldırılır\n• Yer açmak için geçici dosyalar kaldırılır\n\nİzinleri yeniden etkinleştirmek için uygulamayı açın."</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{En son # aydan fazla bir süre önce açıldı}other{En son # aydan uzun bir süre önce açıldı}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{En son # aydan uzun bir süre önce açıldı}other{En son # aydan uzun bir süre önce açıldı}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"Uygulama en son <xliff:g id="DATE">%s</xliff:g> tarihinde açıldı"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"En son <xliff:g id="DATE">%s</xliff:g> tarihinde açıldı"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Tüm dosyaların yönetilmesine izin verirseniz bu uygulama, bu cihazdaki ortak depolama alanında veya bu cihaza bağlı depolama cihazlarında bulunan tüm dosyalara erişebilir, bunları değiştirebilir ve silebilir. Uygulama, size sormadan dosyalara erişebilir."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Yardımcı uygulama tetikleyici algılamasını göster"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Sesli yardımı etkinleştirmek için mikrofon kullanıldığında simgeyi durum çubuğunda göster"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının cihazınızdaki fotoğraf ve medya içeriğine erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının kişilerinize erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazın konumuna erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Bu uygulama konum bilgisine yalnızca kullanıldığı sırada erişebilecektir"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazın konumuna erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Bu uygulama, kullanmadığınız sırada bile konum bilginize sürekli olarak erişmek isteyebilir. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; için konum adresi değiştirilsin mi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Bu uygulama, kullanmadığınız sırada bile konum bilginize sürekli olarak erişmek isteyebilir. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına, yakındaki cihazları bulup bağlanma ve göreli konumlarını belirleme izni verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına, yakındaki cihazları bulup bağlanma ve göreli konumlarını belirleme izni verilsin mi? "<annotation id="link">"Ayarlarda izin ver"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> uygulamasının konum erişimi, yaklaşık konumdan tam konuma değiştirilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazın yaklaşık konumuna erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Tam"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Yaklaşık"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının takviminize erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının SMS mesajları göndermesine ve görüntülemesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının cihazınızdaki fotoğraf, medya ve dosyalara erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; için bu cihazdaki &lt;b&gt;fotoğraf, video, müzik ve ses dosyalarına&lt;/b&gt; erişim verilsin mi?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; için cihazdaki &lt;b&gt;fotoğraf, video, müzik, ses vb. dosyalara&lt;/b&gt; erişim verilsin mi?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazda müzik ve ses dosyalarına erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazdaki fotoğraf ve videolara erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının bu cihazdaki diğer fotoğraf ve videolara erişmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının ses kaydetmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Bu uygulama, yalnızca kullanıldığı sırada ses kaydedebilir"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının ses kaydetmesine izin verilsin mi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Bu uygulama, kullanmadığınız sırada bile sürekli olarak ses kaydetmek isteyebilir. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; için mikrofon erişimi değiştirilsin mi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Bu uygulama, kullanmadığınız sırada bile sürekli olarak ses kaydetmek istiyor. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına fiziksel aktivitenize erişme izni verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının fotoğraf çekmesine ve video kaydı yapmasına izin verilsin mi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Bu uygulama, yalnızca kullanıldığı sırada resim çekebilir veya video kaydedebilir"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının resim çekmesine ve video kaydı yapmasına izin verilsin mi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Bu uygulama, kullanmadığınız sırada bile sürekli olarak resim çekmek ve video kaydetmek isteyebilir. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; için kamera erişimi değiştirilsin mi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Bu uygulama, kullanmadığınız sırada bile sürekli olarak resim çekmek ve video kaydetmek istiyor. "<annotation id="link">"Ayarlar\'da izin verin."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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="auto_granted_permissions" msgid="6009452264824455892">"Kontrol edilen izinler"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Kontrol edilen izinler"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> konuma erişebiliyor"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Kuruluşunuz <xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasının konumunuza erişmesine izin veriyor"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Diğer izinler"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Sistem tarafından kullanılan izinler"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Yalnızca sistem uygulamaları tarafından kullanılan izinler."</string>
@@ -585,12 +637,13 @@
<string name="mic_toggle_description" msgid="9163104307990677157">"Uygulamalar ve hizmetler için. Bu ayar kapalıyken bir acil durum numarasını aradığınızda mikrofon verileri paylaşılmaya devam edilebilir."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Konum erişimi olan uygulama ve hizmetlere göz atın."</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Panoya erişimi göster"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Uygulamalar kopyaladığınız metne, resimlere veya diğer içeriklere eriştiğinde mesaj gösterilsin."</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Uygulamalar kopyaladığınız metne, resimlere veya diğer içeriklere eriştiğinde mesaj gösterilsin"</string>
<string name="show_password_title" msgid="2877269286984684659">"Şifreleri göster"</string>
<string name="show_password_summary" msgid="1110166488865981610">"Yazarken karakterleri kısa süreliğine göster"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Bu uygulama, konum verilerini üçüncü taraflarla paylaşabileceğini belirtti"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Veri paylaşımı ve konum"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Veri paylaşımı bilgilerinin kaynağı"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Geliştirici, bu cihazın üreticisine bu uygulamanın veri paylaşım yöntemleri hakkında bilgi sağladı. Geliştirici bu bilgiyi zaman içinde güncelleyebilir."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Geliştirici, "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" uygulama mağazasına bu uygulamanın veri paylaşımı yöntemleri hakkında bilgi sağladı. Geliştirici bu bilgiyi zaman içinde güncelleyebilir."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Bu uygulama, konum verilerini paylaşabilir:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Veri paylaşımı değişir"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Veri güvenliği"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Konum verileri paylaşılabilir"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Bu uygulama, konum verilerinizi üçüncü taraflarla paylaşabileceğini belirtti"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Bu bağlantı açılamıyor"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Konum için veri paylaşımı güncellemeleri"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Konum verilerinizi paylaşma şekillerini değiştiren uygulamaları inceleyin"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Bu uygulamalar, konum verilerinizi paylaşma şekillerini değiştirdi. Daha önce paylaşmadıkları konum verilerinizi paylaşmaya başlamış olabilecekleri gibi reklam ya da pazarlama için paylaşmaya başlamış da olabilirler."</string>
diff --git a/PermissionController/res/values-uk-v33/strings.xml b/PermissionController/res/values-uk-v33/strings.xml
index 5ea1b68cb..0066766f5 100644
--- a/PermissionController/res/values-uk-v33/strings.xml
+++ b/PermissionController/res/values-uk-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Більше сповіщень"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Закриті сповіщення"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Розгорніть і перегляньте ще одне сповіщення}one{Розгорніть і перегляньте ще # сповіщення}few{Розгорніть і перегляньте ще # сповіщення}many{Розгорніть і перегляньте ще # сповіщень}other{Розгорніть і перегляньте ще # сповіщення}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Сповіщення. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Дію виконано"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Перевірте налаштування, які можуть посилити захист вашого пристрою"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Швидкі налаштування безпеки й конфіденційності"</string>
diff --git a/PermissionController/res/values-uk-v34/strings.xml b/PermissionController/res/values-uk-v34/strings.xml
index 30c8e75b9..5d14c8ebe 100644
--- a/PermissionController/res/values-uk-v34/strings.xml
+++ b/PermissionController/res/values-uk-v34/strings.xml
@@ -18,10 +18,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="security_privacy_brand_name" msgid="7303621734258440812">"Безпека й конфіденційність"</string>
- <string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Елементи керування"</string>
+ <string name="privacy_subpage_controls_header" msgid="4152396976713749322">"Параметри"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
- <string name="health_connect_summary" msgid="815473513776882296">"Керуйте доступом додатка до даних про здоров’я"</string>
+ <string name="health_connect_summary" msgid="815473513776882296">"Керуйте доступом додатків до даних про здоров’я"</string>
<string name="location_settings" msgid="8863940440881290182">"Доступ до геоданих"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Для додатків і сервісів. Якщо це налаштування вимкнено, дані мікрофона можуть усе одно передаватися під час виклику екстреного номера"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Для додатків і сервісів. Якщо це налаштування вимкнено, дані мікрофона можуть усе одно передаватися під час виклику екстреного номера."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Для додатків і сервісів"</string>
</resources>
diff --git a/PermissionController/res/values-uk/strings.xml b/PermissionController/res/values-uk/strings.xml
index ab9258484..97f6dc0d1 100644
--- a/PermissionController/res/values-uk/strings.xml
+++ b/PermissionController/res/values-uk/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Усе одно не дозволяти"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Закрити"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> з <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; таке: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Завжди дозволяти додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; таке: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Завжди дозволяти додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Лише коли додаток активний"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Завжди"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Не дозволяти й більше не запитувати"</string>
@@ -71,7 +71,7 @@
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{Сьогодні}=1{1 день тому}one{# день тому}few{# дні тому}many{# днів тому}other{# дня тому}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"Вимкнути додаток"</string>
<string name="app_disable_dlg_text" msgid="3126943217146120240">"Якщо вимкнути цей додаток, система Android та інші додатки можуть працювати неналежним чином. Важливо: ви не можете видалити цей додаток, оскільки він був попередньо встановлений на пристрої. Вимкнений додаток буде приховано."</string>
- <string name="app_permission_manager" msgid="3903811137630909550">"Диспетчер дозволів"</string>
+ <string name="app_permission_manager" msgid="3903811137630909550">"Менеджер дозволів"</string>
<string name="never_ask_again" msgid="4728762438198560329">"Більше не запитувати"</string>
<string name="no_permissions" msgid="3881676756371148563">"Немає дозволів"</string>
<string name="additional_permissions" msgid="5801285469338873430">"Додаткові дозволи"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Показувати значок очікування активатора асистента"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Показувати значок у рядку стану, коли мікрофон працює в режимі очікування активатора голосового помічника"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до фото й медіа на пристрої?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до контактів?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до місцезнаходження пристрою?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Додаток матиме доступ до геоданих, лише коли ви ним користуєтеся"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до місцезнаходження пристрою?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Додаток може запитувати доступ до ваших геоданих, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Змінити доступ до геоданих для додатка &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Додаток хоче завжди отримувати доступ до ваших геоданих, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Дозволити додатку <xliff:g id="APP_NAME">%1$s</xliff:g> знаходити пристрої поблизу, підключатися до них і визначати їх відносне розташування?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Дозволити додатку <xliff:g id="APP_NAME">%1$s</xliff:g> знаходити пристрої поблизу, підключатися до них і визначати їх відносне розташування? "<annotation id="link">"Дозвольте в налаштуваннях."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Змінити доступ до місцезнаходження для додатка <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> з приблизного на точне?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до приблизного місцезнаходження пристрою?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Точне"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Приблизне"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до календаря?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; надсилати та переглядати SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до фото, медіа та файлів на пристрої?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до &lt;b&gt;фото, відео, музики й аудіо&lt;/b&gt; на цьому пристрої?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до &lt;b&gt;фото, відео, музики, аудіо й інших файлів&lt;/b&gt; на пристрої?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до музики й аудіофайлів на цьому пристрої?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до фотографій і відео на цьому пристрої?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до інших фото й відео на цьому пристрої?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записувати аудіо?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Додаток зможе записувати звук, лише коли ви використовуєте його"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записувати звук?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Цей додаток може записувати звук, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Змінити налаштування доступу до мікрофона для додатка &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Цей додаток може записувати звук, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до даних про фізичну активність?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; робити знімки та записувати відео?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Додаток зможе робити фотографії та записувати відео, лише коли ви використовуєте його"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; робити знімки й записувати відео?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Цей додаток може робити фотографії та записувати відео, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Змінити налаштування доступу до камери для додатка &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Цей додаток може робити фотографії та записувати відео, навіть коли ви не використовуєте його. Дозвіл можна надати в "<annotation id="link">"налаштуваннях"</annotation>"."</string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до журналів викликів телефона?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; здійснювати телефонні дзвінки та керувати ними?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"Надати додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; доступ до життєвих показників із датчиків?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Щоб надати додатку постійний доступ до показників датчиків на тілі, навіть коли він не використовується, "<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="auto_granted_permissions" msgid="6009452264824455892">"Керовані дозволи"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; надсилати вам сповіщення?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Керовані дозволи"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> має доступ до геоданих"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Ваша організація надає додатку <xliff:g id="APP_NAME">%1$s</xliff:g> доступ до ваших геоданих"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Інші дозволи"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Дозволи, які використовує система"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Дозволи, які використовують лише системні додатки."</string>
@@ -515,7 +567,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"Минулі\n24 години"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"Останні\n7 днів"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами чи в рядку стану."</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами чи в рядку стану."</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> захищено системою Android. Оскільки ваші дані обробляються на цьому пристрої, дозволи, які використовує цей додаток, не відображаються на панелі керування дозволами."</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"Камеру пристрою заблоковано"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"Мікрофон пристрою заблоковано"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"Геодані пристрою вимкнено"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Цей додаток зазначає, що може передавати дані про місцезнаходження третім особам"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Передавання даних і місцезнаходження"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Звідки надходить інформація про передавання даних"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Розробник надав виробнику цього пристрою інформацію про те, як цей додаток передає дані. Розробник може періодично оновлювати цю інформацію."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Розробник надав "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" інформацію про те, як цей додаток передає дані. Розробник може періодично оновлювати цю інформацію."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Цілі передавання геоданих цим додатком"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Спосіб передавання даних може різнитися"</string>
@@ -608,9 +661,7 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Безпека даних"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Можуть передаватися геодані"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Цей додаток повідомляє, що може передавати ваші геодані третім особам"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Не вдається відкрити це посилання"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
- <string name="data_sharing_updates_title" msgid="7996933386875213859">"Оновлення способу передавання геоданих"</string>
+ <string name="data_sharing_updates_title" msgid="7996933386875213859">"Зміни в передаванні геоданих"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Перегляньте додатки, які змінили спосіб передавання ваших геоданих"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Ці додатки змінили спосіб передавання ваших геоданих. Можливо, ваші дані раніше не передавалися або тепер вони можуть використовуватися для реклами й маркетингу."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Розробники надали магазину додатків інформацію про свої методи передавання даних. Вони можуть періодично вносити зміни в цю інформацію.\n\nМетоди передавання даних можуть різнитися залежно від версії додатка, його використання, регіону й віку користувача."</string>
diff --git a/PermissionController/res/values-ur-v33/strings.xml b/PermissionController/res/values-ur-v33/strings.xml
index b3bcc412d..0a56dd190 100644
--- a/PermissionController/res/values-ur-v33/strings.xml
+++ b/PermissionController/res/values-ur-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"مزید الرٹس"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"برخاست کردہ الرٹس"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{پھیلائیں اور ایک اور الرٹ دیکھیں}other{پھیلائیں اور # مزید الرٹس دیکھیں}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"الرٹ۔ <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"کارروائی مکمل ہو گئی"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"اپنے آلہ کو تحفظ دینے والی ترتیبات چیک کریں"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"سیکیورٹی اور رازداری کی فوری ترتیبات"</string>
diff --git a/PermissionController/res/values-ur/strings.xml b/PermissionController/res/values-ur/strings.xml
index c0f7022dd..cfcee501e 100644
--- a/PermissionController/res/values-ur/strings.xml
+++ b/PermissionController/res/values-ur/strings.xml
@@ -367,12 +367,12 @@
<string name="role_sms_request_title" msgid="7953552109601185602">"‏<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی ڈیفالٹ SMS ایپ کے بطور سیٹ کریں؟"</string>
<string name="role_sms_request_description" msgid="2691004766132144886">"‏اس ایپ کو آپ کے کیمرا، رابطوں، فائلز اور میڈیا، مائیکروفون، فون اور SMS تک رسائی دی جائے گی"</string>
<string name="role_sms_search_keywords" msgid="8022048144395047352">"ٹیکسٹ پیغام، پیغام بھیجنا، پیغامات، پیغام رسانی"</string>
- <string name="role_emergency_label" msgid="7028825857206842366">"ڈیفالٹ ہنگامی ایپ"</string>
- <string name="role_emergency_short_label" msgid="2388431453335350348">"ہنگامی ایپ"</string>
- <string name="role_emergency_description" msgid="5051840234887686630">"وہ ایپس جو آپ کو آپ کی طبی معلومات ریکارڈ کرنے اور اسے ہنگامی طبی مدد فراہم کنندگان کے لیے قابل رسائی بنانے؛ خطرناک موسمی واقعات اور آفات کے بارے میں الرٹس حاصل کرنے؛ آپ کو مدد درکار ہونے پر دوسروں کو اطلاع دینے کی اجازت دیتی ہیں"</string>
- <string name="role_emergency_request_title" msgid="8469579020654348567">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی ڈیفالٹ ہنگامی ایپ کے بطور سیٹ کریں؟"</string>
+ <string name="role_emergency_label" msgid="7028825857206842366">"ڈیفالٹ ایمرجنسی ایپ"</string>
+ <string name="role_emergency_short_label" msgid="2388431453335350348">"ایمرجنسی ایپ"</string>
+ <string name="role_emergency_description" msgid="5051840234887686630">"وہ ایپس جو آپ کو آپ کی طبی معلومات ریکارڈ کرنے اور اسے ایمرجنسی طبی مدد فراہم کنندگان کے لیے قابل رسائی بنانے؛ خطرناک موسمی واقعات اور آفات کے بارے میں الرٹس حاصل کرنے؛ آپ کو مدد درکار ہونے پر دوسروں کو اطلاع دینے کی اجازت دیتی ہیں"</string>
+ <string name="role_emergency_request_title" msgid="8469579020654348567">"<xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کی ڈیفالٹ ایمرجنسی ایپ کے بطور سیٹ کریں؟"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"کوئی اجازت درکار نہیں ہے"</string>
- <string name="role_emergency_search_keywords" msgid="1920007722599213358">"ہنگامی، آئس، ایپ، ڈیفالٹ"</string>
+ <string name="role_emergency_search_keywords" msgid="1920007722599213358">"ایمرجنسی، آئس، ایپ، ڈیفالٹ"</string>
<string name="role_home_label" msgid="3871847846649769412">"ڈیفالٹ ہوم ایپ"</string>
<string name="role_home_short_label" msgid="8544733747952272337">"ہوم ایپ"</string>
<string name="role_home_description" msgid="7997371519626556675">"‏وہ ایپس، جنہیں اکثر لانچرز کہا جاتا ہے، جو آپ کے Android آلہ پر ہوم اسکرینز کی جگہ لے لیتی ہیں اور آپ کے آلہ کے مواد اور خصوصیات تک آپ کو رسائی فراہم کرتی ہیں"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"اسسٹنٹ ٹریگر کا پتہ لگانا دکھائیں"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"جب صوتی معاون کو فعال کرنے کے لیے مائیکروفون کا استعمال کیا جائے تو اسٹیٹس بار میں آئیکن دکھائیں"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو آپ کے آلہ پر تصاویر اور میڈیا تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے رابطوں تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو اس آلہ کے مقام تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"جب آپ ایپ استعمال کریں گے تبھی ایپ کو مقام تک رسائی حاصل ہوگی"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو اس آلہ کے مقام تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"ممکن ہے یہ ایپ ہر وقت آپ کے مقام تک رسائی حاصل کرنا چاہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link"></annotation>"ترتیبات میں اجازت دیں۔"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کے ليے مقام تک رسائی تبدیل کریں"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"یہ ایپ ہر وقت آپ کے مقام تک رسائی حاصل کرنا چاہتی ہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link"></annotation>"ترتیبات میں اجازت دیں۔"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو قریبی آلات تلاش کرنے، ان سے منسلک ہونے اور ان کی متعلقہ پوزیشن کا تعین کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو قریبی آلات تلاش کرنے، ان سے منسلک ہونے اور ان کی متعلقہ پوزیشن کا تعین کرنے کی اجازت دیں؟ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> کے مقام تک رسائی کو تخمینی سے قطعی میں تبدیل کریں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو اس آلے کے تخمینی مقام تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"قطعی"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"تخمینی"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے کیلنڈر تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو SMS پیغامات بھیجنے اور انہیں ملاحظہ کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے آلہ پر تصاویر، میڈیا اور فائلوں تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"‏اس آلے پر &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو &lt;b&gt;تصاویر، ویڈیوز، موسیقی اور آڈیو&lt;/b&gt; تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"‏اس آلے پر &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو &lt;b&gt;تصاویر، ویڈیوز، موسیقی، آڈیو اور دیگر فائلز&lt;/b&gt; تک رسائی کی اجازت دیں؟"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"‏اس آلے پر &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو موسیقی اور آڈیو تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"‏اس آلے پر &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو اس آلے پر مزید تصاویر اور ویڈیوز تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"جب آپ ایپ استعمال کر رہے ہوں تب ایپ صرف آڈیو ریکارڈ کر پائے گی"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"ممکن ہے یہ ایپ ہر وقت آڈیو ریکارڈ کرنا چاہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;? کے ليے مائیکروفون تک رسائی تبدیل کریں؟"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"یہ ایپ ہر وقت آڈیو ریکارڈ کرنا چاہتی ہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt;‎ کو آپ کی جسمانی سرگرمی کی شناخت کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو تصاویر لینے اور ویڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"جب آپ ایپ استعمال کر رہے ہوں تب ایپ صرف تصاویر لے سکے گی اور ویڈیوز ریکارڈ کر پائے گی"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو تصاویر لینے اور ویڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"ممکن ہے یہ ایپ ہر وقت تصاویر لینا اور ویڈیو ریکارڈ کرنا چاہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;? کے ليے کیمرا تک رسائی تبدیل کریں؟"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"یہ ایپ ہر وقت تصاویر لینا اور ویڈیو ریکارڈ کرنا چاہتی ہے، اگرچہ آپ ایپ استعمال نہ کر رہے ہوں۔ "<annotation id="link">"ترتیبات میں اجازت دیں۔"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"‏‎&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;‎ کو آپ کے فون کال لاگز تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"‏&lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو فون کالز کرنے اور ان کا نظم کرنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کے اہم اشاروں کے متعلق سینسر ڈیٹا تک رسائی کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"آپ کے ایپ کا استعمال نہ کرنے کے باوجود اس ایپ کو ہر وقت باڈی سینسر ڈیٹا تک رسائی کی اجازت دینے کے لیے "<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="auto_granted_permissions" msgid="6009452264824455892">"کنٹرول کی گئی اجازتیں"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>‏&lt;/b&gt; کو آپ کو اطلاعات بھیجنے کی اجازت دیں؟"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"کنٹرول کی گئی اجازتیں"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے پاس مقام تک رسائی حاصل ہے"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"آپ کی تنظیم <xliff:g id="APP_NAME">%1$s</xliff:g> کو آپ کے مقام تک رسائی کی اجازت دیتی ہے"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"دیگر اجازتیں"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"سسٹم کے ذریعے استعمال کردہ اجازتیں"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"صرف سسٹم ایپلیکیشنز کے ذریعے استعمال کردہ اجازتیں۔"</string>
@@ -549,7 +601,7 @@
<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>
- <string name="recent_app_usage_qs" msgid="6650259601306212327">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے ذریعے حال ہی میں استعمال کیا گیا"</string>
+ <string name="recent_app_usage_qs" msgid="6650259601306212327">"حال ہی میں <xliff:g id="APP_NAME">%1$s</xliff:g> نے استعمال کیا"</string>
<string name="active_app_usage_1_qs" msgid="4325136375823357052">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) کے ذریعے استعمال کیا جا رہا ہے"</string>
<string name="recent_app_usage_1_qs" msgid="261450184773310741">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g>) کے ذریعے حال ہی میں استعمال کیا گیا"</string>
<string name="active_app_usage_2_qs" msgid="6107866785243565283">"<xliff:g id="APP_NAME">%1$s</xliff:g> (<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>) کے ذریعے استعمال کیا جا رہا ہے"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"اس ایپ نے بتایا ہے کہ یہ مقام کے ڈیٹا کا اشتراک فریقین ثالث کے ساتھ کر سکتی ہے"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"ڈیٹا کا اشتراک اور مقام"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"ڈیٹا کے اشتراک کی معلومات کا ذریعہ"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"ڈویلپر نے اس آلہ کے مینوفیکچرر کو معلومات فراہم کی کہ یہ ایپ ڈیٹا کا اشتراک کیسے کرتی ہے۔ ڈویلپر وقت کے ساتھ اس معلومات کو اپ ڈیٹ کر سکتا ہے۔"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"‏ڈویلپر نے "<annotation id="link"><annotation id="install_source" example="App Store">"‏%1$s"</annotation></annotation>" کو معلومات فراہم کی کہ یہ ایپ ڈیٹا کا اشتراک کیسے کرتی ہے۔ ڈویلپر وقت کے ساتھ اس معلومات کو اپ ڈیٹ کر سکتا ہے۔"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"یہ ایپ ذیل کے لیے مقام کے ڈیٹا کا اشتراک کر سکتی ہے:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"ڈیٹا کا اشتراک مختلف ہوتا ہے"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"ڈیٹا کی حفاظت"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"مقام کے ڈیٹا کا اشتراک کیا جا سکتا ہے"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"اس ایپ نے بتایا ہے کہ یہ آپ کے مقام کے ڈیٹا کا اشتراک فریقین ثالث کے ساتھ کر سکتی ہے"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"اس لنک کو کھولا نہیں جا سکتا"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"مقام کیلئے ڈیٹا کے اشتراک کی اپ ڈیٹس"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"ان ایپس کا جائزہ لیں جنہوں نے آپ کے مقام کے ڈیٹا کے اشتراک کے اپنے ممکنہ طریقے کو تبدیل کر دیا"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"ان ایپس نے آپ کے مقام کے ڈیٹا کے اشتراک کے اپنے ممکنہ طریقے کو تبدیل کر دیا ہے۔ ہو سکتا ہے کہ انہوں نے پہلے اس کا اشتراک نہ کیا ہو یا ممکنہ طور پر اب تشہیر یا مارکیٹنگ کے مقاصد کے لیے اس کا اشتراک کر سکتی ہیں۔"</string>
diff --git a/PermissionController/res/values-uz-v33/strings.xml b/PermissionController/res/values-uz-v33/strings.xml
index 45b7b7248..a32387c37 100644
--- a/PermissionController/res/values-uz-v33/strings.xml
+++ b/PermissionController/res/values-uz-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Boshqa ogohlantirishlar"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Ogohlantirishlar yopildi"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Kengaytirish va yana bitta ogohlantirishni ochish}other{Kengaytirish va yana # ta ogohlantirishni ochish}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Ogohlantirish: <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Amal bajarildi"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Qurilmangizga himoya qoʻshadigan sozlamalarni tekshiring"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Xavfsizlik va maxfiylik tezkor sozlamalari"</string>
diff --git a/PermissionController/res/values-uz/strings.xml b/PermissionController/res/values-uz/strings.xml
index f3dbf18bc..66dad52bc 100644
--- a/PermissionController/res/values-uz/strings.xml
+++ b/PermissionController/res/values-uz/strings.xml
@@ -32,7 +32,7 @@
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"“Ilova ishlatilganda” rejimida qolsin"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“Faqat shu safar” ruxsat berish"</string>
<string name="grant_dialog_button_more_info" msgid="213350268561945193">"Batafsil"</string>
- <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Hammasiga ruxsat berish"</string>
+ <string name="grant_dialog_button_allow_all" msgid="5939066403732409516">"Hammasiga ruxsat"</string>
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"Doim hammasiga ruxsat berish"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"Surat va videolarni tanlash"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"Yana"</string>
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Baribir rad etilsin"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Yopish"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga <xliff:g id="ACTION">%2$s</xliff:g> uchun ruxsat berilsinmi?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ilovasiga bu amalga bajarishga doim ruxsat berilsinmi: <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun <xliff:g id="ACTION">%2$s</xliff:g> ruxsati berilsinmi?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun doim <xliff:g id="ACTION">%2$s</xliff:g> ruxsati berilsinmi?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Faqat ilova ishlatilayotganda"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Har doim"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Rad etilsin va boshqa soʻralmasin"</string>
@@ -124,7 +124,7 @@
<string name="current_permissions_category" msgid="4292990083585728880">"Joriy ruxsatlar"</string>
<string name="message_staging" msgid="9110563899955511866">"Kutib turing…"</string>
<string name="app_name_unknown" msgid="1319665005754048952">"Noaniq"</string>
- <string name="permission_usage_title" msgid="1568233336351734538">"Maxfiylik boshqaruv paneli"</string>
+ <string name="permission_usage_title" msgid="1568233336351734538">"Maxfiylik boshqaruvi"</string>
<string name="auto_permission_usage_summary" msgid="7335667266743337075">"Ruxsatlardan yaqinda foydalangan ilovalarni koʻrish"</string>
<string name="permission_group_usage_title" msgid="2595013198075285173">"<xliff:g id="PERMGROUP">%1$s</xliff:g> ruxsatidan foydalanish"</string>
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Boshqa ruxsatlarni koʻrish"</string>
@@ -226,7 +226,7 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Oxirgi marta ochilgan: <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Barcha fayllarni boshqarishga ruxsat berilsa, ilova bu qurilmadagi yoki ulangan xotira omborlaridagi barcha fayllarni ochishi, tahrirlashi yoki oʻchirib tashlashi mumkin. Ilova fayllar bilan sizga xabar qilmay ishlay oladi."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Ilovaga bu qurilmadagi yoki ulangan xotira omborlaridagi barcha fayllarni ochish, tahrirlash yoki oʻchirib tashlash uchun ruxsat berilsinmi? Bu ilova fayllar bilan sizga xabar qilmay ishlay oladi."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Bunday ruxsatga ega ilovalar quyidagi amallarni bajara oladi: <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"<xliff:g id="DESCRIPTION">%1$s</xliff:g> ruxsatiga ega ilovalar"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Bunday ruxsatga ega ilovalar piyoda yurish, velosiped haydash, avtomobil boshqarish, qadamlaringiz soni kabi jismoniy faoliyatingiz haqidagi axborotlarga ham kira oladi"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Bunday ruxsatga ega ilovalar taqvimingizdan foydalana oladi"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Bunday ruxsatga ega ilovalar telefondagi chaqiruvlar jurnaliga kira oladi va uni tahrirlay oladi"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Ovozli yordamchi faollashgani haqidagi belgini chiqarish"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Ovozli yordamchi mikrofon orqali faollashtirilganda, bu haqda holat qatorida maxsus belgi chiqadi"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun qurilmadagi suratlar va media fayllarga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun kontaktlaringizga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun bu qurilmaning joylashuvi haqidagi axborotdan foydalanish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Bu ilovadan foydalanilayotdangina u joylashuv axborotidan foydalana oladi"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun bu qurilmaning joylashuvi haqidagi axborotdan foydalanish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Bu ilova ochiq emasligida ham joylashuvingiz haqidagi axborotdan foydalanmoqchi. Bunga "<annotation id="link">" sozlamalar"</annotation>" orqali ruxsat bering."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun joylashuv axborotiga ruxsat oʻzgartirilsinmi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Bu ilova ochiq emasligida ham joylashuvingiz haqidagi axborotdan foydalanmoqchi. Bunga "<annotation id="link">"sozlamalar"</annotation>" orqali ruxsat bering."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; yaqin-atrofdagi qurilmalar joylashuvini aniqlashi va ularga ulanishiga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; yaqin-atrofdagi qurilmalar joylashuvini aniqlashi va ularga ulanishiga ruxsat berilsinmi? "<annotation id="link">"Sozlamalar orqali ruxsat berish mumkin."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> uchun joylashuv ruxsati taxminiydan aniqqa oʻzgartirilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun bu qurilmaning taxminiy joylashuvi haqidagi axborotdan foydalanish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Aniq"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Taxminiy"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun taqvimingizga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun SMS xabarlarni yuborish va ko‘rishga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun qurilmangizdagi suratlar, multimedia va fayllarga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun ushbu qurilmadagi surat, video, musiqa va audiolarga kirish ruxsati berilsinmi?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun ushbu qurilmadagi surat, video, musiqa, audio va fayllarga kirish ruxsati berilsinmi?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun ushbu qurilmadagi musiqa va audio fayllarga kirish ruxsati berilsinmi?"</string>
- <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun qurilmadagi rasm va videolarga kirish ruxsati berilsinmi?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun qurilmadagi boshqa rasm va videolarga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
+ <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun qurilmadagi suratlar va videolarga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun qurilmadagi boshqa surat va videolarga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun audio yozib olish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Bu ilova faqat undan foydalanganingizda ovozlarni yozib oladi"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun audio yozib olishga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Bu ilova doimo, hatto undan foydalanmagan vaqtlaringizda ham ovoz yozib olishi mumkin. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun mikrofonga ruxsat oʻzgartirilsinmi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Bu ilova doimo, hatto undan foydalanmagan vaqtlaringizda ham ovoz yozib olishi mumkin. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun jismoniy harakatlaringizga oid axborotga kirish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun surat va videoga olish ruxsati berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Bu ilova faqat undan foydalanganingizda rasm va videoga oladi"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun surat va videoga olishga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Bu ilova doimo, hatto undan foydalanmagan vaqtlaringizda ham rasm va videoga olishi mumkin. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun kameraga ruxsat oʻzgartirilsinmi?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Bu ilova doimo, hatto undan foydalanmagan vaqtlaringizda ham rasm va videoga olishi mumkin. "<annotation id="link">"Sozlamalar orqali ruxsat bering."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun tana holati haqidagi sensor axborotlariga ruxsat berilsinmi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"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; ilovasining tanadagi sensor maʼlumotlaridan foydalanishiga ruxsat berilsinmi?"</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="auto_granted_permissions" msgid="6009452264824455892">"Boshqariluvchi ruxsatlar"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Boshqariluvchi ruxsatlar"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> joylashuvga kira oladi"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Tashkilotingiz <xliff:g id="APP_NAME">%1$s</xliff:g> ilovasiga joylashuvingizga kirishga ruxsat bergan"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Boshqa ruxsatlar"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Tizim ishlatadigan ruxsatlar"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Faqat tizim ilovalari ishlatadigan ruxsatlar"</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Bu ilovaning maʼlumotlarini begonalarga ulashishi mumkinligi xabar berildi"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Maʼlumotlar ulashuvi va joylashuv axboroti"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Maʼlumotlar ulashuvi haqidagi axborot manbasi"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Dasturchi bu qurilma ishlab chiqaruvchisiga ushbu ilova maʼlumotlarni qanday ulashishi haqida axborot berdi. Bu axborot keyinchalik yangilanishi mumkin."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Dasturchi "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" ga bu ilovadagi maʼlumotlar qanday ulashilishi haqida axborot bergan. Bu axborot keyinchalik yangilanishi mumkin."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ilova joylashuv axborotini quyidagicha ulashadi:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Maʼlumotlarning turlicha ulashuvi"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Maʼlumotlar xavfsizligi"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Joylashuv axboroti ulashilishi mumkin"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Bu ilova tashqariga joylashuv axborotini ulashishi mumkinligi aniqlandi"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Bu havola ochilmadi"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Joylashuv axboroti ulashuvidagi oʻzgarishlar"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Joylashuv axboroti ulashuviga oʻzgartirish kiritgan ilovalarni tekshiring"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Quyidagi ilovalarda joylashuv axboroti ulashuvi oʻzgardi. Avval ulashilmagan boʻlishi yoki endi reklama va marketing maqsadlarida ulashilishi mumkin"</string>
diff --git a/PermissionController/res/values-v31/styles.xml b/PermissionController/res/values-v31/styles.xml
index a05fd488b..3b42a6e5b 100644
--- a/PermissionController/res/values-v31/styles.xml
+++ b/PermissionController/res/values-v31/styles.xml
@@ -90,16 +90,16 @@
parent="@style/PermissionGrantButtonTop"></style>
<style name="PermissionGrantButtonAllowOneTimeMaterial3"
parent="@style/PermissionGrantButtonMiddle"></style>
+ <style name="PermissionGrantButtonAllowSelectedMaterial3"
+ parent="@style/PermissionGrantButtonTop"></style>
<style name="PermissionGrantButtonAllowAllMaterial3"
parent="@style/PermissionGrantButtonMiddle"></style>
- <style name="PermissionGrantButtonAllowSelectedMaterial3"
- parent="@style/PermissionGrantButtonTop"></style>
- <style name="PermissionGrantButtonDontAllowMoreMaterial3"
- parent="@style/PermissionGrantButtonBottom"></style>
<style name="PermissionGrantButtonDenyMaterial3"
parent="@style/PermissionGrantButtonBottom"></style>
<style name="PermissionGrantButtonNoUpgradeMaterial3"
parent="@style/PermissionGrantButtonBottom"></style>
+ <style name="PermissionGrantButtonDontAllowMoreMaterial3"
+ parent="@style/PermissionGrantButtonBottom"></style>
<!-- END PERMISSION GRANT DIALOG -->
diff --git a/PermissionController/res/values-v33/attrs.xml b/PermissionController/res/values-v33/attrs.xml
index b59716f6d..4a417076d 100644
--- a/PermissionController/res/values-v33/attrs.xml
+++ b/PermissionController/res/values-v33/attrs.xml
@@ -37,7 +37,10 @@
<attr name="scStatusTitleAndSummaryContainerStyle" format="reference" />
<attr name="scStatusButtonStyle" format="reference" />
+ <attr name="scActionButtonListLayout" format="reference" />
+ <attr name="scActionButtonTheme" format="reference" />
<attr name="scActionButtonStyle" format="reference"/>
<attr name="scSecondaryActionButtonStyle" format="reference"/>
+
<attr name="colorScShieldAccent" format="color" />
</resources> \ No newline at end of file
diff --git a/PermissionController/res/values-v33/dimens.xml b/PermissionController/res/values-v33/dimens.xml
index ef70d2711..e6925bc54 100644
--- a/PermissionController/res/values-v33/dimens.xml
+++ b/PermissionController/res/values-v33/dimens.xml
@@ -24,20 +24,25 @@
<dimen name="sc_spacing_xlarge">18dp</dimen>
<dimen name="sc_spacing_xxlarge">20dp</dimen>
<dimen name="sc_spacing_xxxlarge">24dp</dimen>
- <dimen name="sc_large_screen_button_padding">56dp</dimen>
<dimen name="sc_card_margin">@dimen/sc_spacing_xxxsmall</dimen>
<dimen name="sc_list_margin">@dimen/sc_spacing_large</dimen>
<dimen name="sc_list_margin_top">@dimen/sc_spacing_small</dimen>
+
+ <!-- Only used for small screen views, but doesn't have _small_screen suffix since it's fixed in
+ the overlayable. -->
<dimen name="sc_action_button_list_margin">@dimen/sc_spacing_large</dimen>
+ <dimen name="sc_action_button_list_margin_large_screen">@dimen/sc_spacing_large</dimen>
<dimen name="sc_top_action_button_margin">@dimen/sc_spacing_xxxlarge</dimen>
+ <dimen name="sc_button_horizontal_padding_small_screen">@dimen/sc_spacing_xxxlarge</dimen>
+ <dimen name="sc_button_horizontal_padding_large_screen">56dp</dimen>
+
<dimen name="sc_entry_padding_end">@dimen/sc_spacing_xxxlarge</dimen>
<dimen name="sc_entry_group_expanded_padding_top">@dimen/sc_spacing_xxxlarge</dimen>
<dimen name="sc_entry_group_expanded_padding_bottom">@dimen/sc_spacing_xsmall</dimen>
<dimen name="sc_entry_group_collapsed_padding_top">@dimen/sc_spacing_large</dimen>
<dimen name="sc_entry_group_collapsed_padding_bottom">@dimen/sc_spacing_large</dimen>
<dimen name="sc_card_margin_bottom">@dimen/sc_spacing_xxxlarge</dimen>
- <dimen name="sc_button_horizontal_padding">@dimen/sc_spacing_xxxlarge</dimen>
<dimen name="sc_icon_button_touch_target_size">48dp</dimen>
<dimen name="sc_button_corner_radius">12dp</dimen>
diff --git a/PermissionController/res/values-v33/layout.xml b/PermissionController/res/values-v33/layout.xml
new file mode 100644
index 000000000..a963dae0d
--- /dev/null
+++ b/PermissionController/res/values-v33/layout.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="action_button_list_fixed" type="layout">
+ @layout/action_button_list_small_screen
+ </item>
+ <item name="action_button_list_responsive" type="layout">
+ @layout/action_button_list_small_screen
+ </item>
+</resources> \ No newline at end of file
diff --git a/PermissionController/res/values-v33/styles.xml b/PermissionController/res/values-v33/styles.xml
index a0938665f..e4d8f5c54 100644
--- a/PermissionController/res/values-v33/styles.xml
+++ b/PermissionController/res/values-v33/styles.xml
@@ -324,10 +324,10 @@
<style name="SafetyCenterActionButton"
parent="@style/Widget.MaterialComponents.Button.UnelevatedButton">
- <item name="android:theme">@style/Theme.MaterialComponents</item>
+ <item name="android:theme">?attr/scActionButtonTheme</item>
<item name="android:minHeight">56dp</item>
- <item name="android:paddingStart">@dimen/sc_button_horizontal_padding</item>
- <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding</item>
+ <item name="android:paddingStart">@dimen/sc_button_horizontal_padding_small_screen</item>
+ <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding_small_screen</item>
<item name="android:paddingTop">@dimen/sc_spacing_xlarge</item>
<item name="android:paddingBottom">@dimen/sc_spacing_xlarge</item>
<item name="android:insetTop">0dp</item>
@@ -340,13 +340,15 @@
<item name="cornerRadius">@dimen/sc_button_corner_radius</item>
<item name="rippleColor">?android:colorControlHighlight</item>
</style>
+ <style name="SafetyCenterActionButton.Fixed" />
+ <style name="SafetyCenterActionButton.Responsive" />
- <style name="SafetyCenterActionButton.Secondary"
+ <style name="SecondarySafetyCenterActionButton"
parent="@style/Widget.MaterialComponents.Button.OutlinedButton">
- <item name="android:theme">@style/Theme.MaterialComponents</item>
+ <item name="android:theme">?attr/scActionButtonTheme</item>
<item name="android:minHeight">56dp</item>
- <item name="android:paddingStart">@dimen/sc_button_horizontal_padding</item>
- <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding</item>
+ <item name="android:paddingStart">@dimen/sc_button_horizontal_padding_small_screen</item>
+ <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding_small_screen</item>
<item name="android:paddingTop">@dimen/sc_spacing_xlarge</item>
<item name="android:paddingBottom">@dimen/sc_spacing_xlarge</item>
<item name="android:insetTop">0dp</item>
@@ -361,6 +363,8 @@
<item name="cornerRadius">@dimen/sc_button_corner_radius</item>
<item name="rippleColor">?android:colorControlHighlight</item>
</style>
+ <style name="SecondarySafetyCenterActionButton.Fixed" />
+ <style name="SecondarySafetyCenterActionButton.Responsive" />
<!-- START SAFETY STATUS CARD -->
<style name="SafetyCenterCard.Status">
@@ -789,12 +793,6 @@
<item name="android:layout_height">24dp</item>
</style>
- <style name="SafetyCenterNoLabelPreferenceCategory"
- parent="android:Widget.DeviceDefault">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">16dp</item>
- </style>
-
<style name="SafetyCenterGroupEntry"
parent="android:Widget.DeviceDefault">
<item name="android:layout_width">match_parent</item>
diff --git a/PermissionController/res/values-v33/themes.xml b/PermissionController/res/values-v33/themes.xml
index 338cbaa01..82a8ef5b6 100644
--- a/PermissionController/res/values-v33/themes.xml
+++ b/PermissionController/res/values-v33/themes.xml
@@ -47,14 +47,18 @@
<item name="scStatusButtonStyle">@style/SafetyCenterStatusButton.Fixed</item>
<!-- Buttons -->
- <item name="scActionButtonStyle">@style/SafetyCenterActionButton</item>
- <item name="scSecondaryActionButtonStyle">@style/SafetyCenterActionButton.Secondary</item>
+ <item name="scActionButtonListLayout">@layout/action_button_list_fixed</item>
+ <item name="scActionButtonTheme">
+ <!-- Dark-only theme for QS buttons -->
+ @style/Theme.MaterialComponents
+ </item>
+ <item name="scActionButtonStyle">@style/SafetyCenterActionButton.Fixed</item>
+ <item name="scSecondaryActionButtonStyle">
+ @style/SecondarySafetyCenterActionButton.Fixed
+ </item>
<item name="textColorScActionButton">@color/sc_primary_action_button_text</item>
- <!-- While the rest of the text colors automatically appear correct in quick settings,
- the outline action button text color needs to be set to primary inverse in light mode
- and primary in night mode to appear correctly in QS's faux permanent night mode. -->
- <item name="textColorScSecondaryActionButton">?android:attr/textColorPrimaryInverse</item>
+ <item name="textColorScSecondaryActionButton">?android:attr/textColorPrimary</item>
<item name="colorScOutlineButtonInfoBase">@color/sc_outline_button_info_base_dark</item>
<item name="colorScOutlineButtonRecommendBase">
@@ -93,8 +97,12 @@
<item name="scStatusButtonStyle">@style/SafetyCenterStatusButton.Responsive</item>
<!-- Buttons -->
- <item name="scActionButtonStyle">@style/SafetyCenterActionButton</item>
- <item name="scSecondaryActionButtonStyle">@style/SafetyCenterActionButton.Secondary</item>
+ <item name="scActionButtonListLayout">@layout/action_button_list_responsive</item>
+ <item name="scActionButtonTheme">@style/Theme.MaterialComponents.DayNight</item>
+ <item name="scActionButtonStyle">@style/SafetyCenterActionButton.Responsive</item>
+ <item name="scSecondaryActionButtonStyle">
+ @style/SecondarySafetyCenterActionButton.Responsive
+ </item>
<item name="textColorScActionButton">@color/sc_primary_action_button_text</item>
<item name="textColorScSecondaryActionButton">?android:attr/textColorPrimary</item>
diff --git a/PermissionController/res/values-v34/strings.xml b/PermissionController/res/values-v34/strings.xml
index 30181aa02..26a9b4bcc 100644
--- a/PermissionController/res/values-v34/strings.xml
+++ b/PermissionController/res/values-v34/strings.xml
@@ -28,7 +28,7 @@
<!-- Title for the link to location settings [CHAR LIMIT=30] -->
<string name="location_settings">Location access</string>
- <!-- Describes what is affected by the mic toggle [CHAR LIMIT=NONE] -->
+ <!-- Describes what is affected by the mic toggle. Unlike the similar tc/9163104307990677157, there should NOT be a full stop at the end of this sentence. [CHAR LIMIT=NONE] -->
<string name="mic_toggle_description">For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number</string>
<!-- Subtitle for the link to location settings [CHAR LIMIT=NONE] -->
<string name="location_settings_subtitle">For apps and services</string>
diff --git a/PermissionController/res/values-v35/bools.xml b/PermissionController/res/values-v35/bools.xml
new file mode 100644
index 000000000..f015b636e
--- /dev/null
+++ b/PermissionController/res/values-v35/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright 2023 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>
+ <bool name="is_at_least_v">true</bool>
+</resources>
diff --git a/PermissionController/res/values-vi-v33/strings.xml b/PermissionController/res/values-vi-v33/strings.xml
index b5d70029e..d5fdffc1e 100644
--- a/PermissionController/res/values-vi-v33/strings.xml
+++ b/PermissionController/res/values-vi-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Cảnh báo khác"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Cảnh báo bị loại bỏ"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Mở rộng và xem một cảnh báo khác}other{Mở rộng và xem # cảnh báo khác}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Cảnh báo. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Hoàn tất hành động"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Kiểm tra các chế độ cài đặt có thể giúp tăng cường bảo vệ cho thiết bị của bạn"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Các tùy chọn cài đặt nhanh về bảo mật và quyền riêng tư"</string>
diff --git a/PermissionController/res/values-vi-v34/strings.xml b/PermissionController/res/values-vi-v34/strings.xml
index 22832fc8d..618a266d8 100644
--- a/PermissionController/res/values-vi-v34/strings.xml
+++ b/PermissionController/res/values-vi-v34/strings.xml
@@ -22,6 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"Quản lý quyền truy cập của ứng dụng vào dữ liệu sức khoẻ"</string>
<string name="location_settings" msgid="8863940440881290182">"Quyền truy cập thông tin vị trí"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"Ảnh hưởng đến các ứng dụng và dịch vụ. Nếu tắt chế độ cài đặt này, dữ liệu thu được qua micrô vẫn có thể được chia sẻ khi bạn gọi đến số khẩn cấp"</string>
- <string name="location_settings_subtitle" msgid="6846532794702613851">"Đối với các ứng dụng và dịch vụ"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"Áp dụng cho các ứng dụng và dịch vụ. Nếu bạn tắt chế độ cài đặt này, dữ liệu thu được qua micrô vẫn có thể được chia sẻ khi bạn gọi đến số khẩn cấp"</string>
+ <string name="location_settings_subtitle" msgid="6846532794702613851">"Áp dụng cho các ứng dụng và dịch vụ"</string>
</resources>
diff --git a/PermissionController/res/values-vi/strings.xml b/PermissionController/res/values-vi/strings.xml
index fac51befe..537e23f78 100644
--- a/PermissionController/res/values-vi/strings.xml
+++ b/PermissionController/res/values-vi/strings.xml
@@ -40,8 +40,8 @@
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"Vẫn không cho phép"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"Đóng"</string>
<string name="current_permission_template" msgid="7452035392573329375">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g>/<xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
- <string name="permission_warning_template" msgid="2247087781222679458">"Bạn có muốn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> không?"</string>
- <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Bạn có muốn luôn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g> không?"</string>
+ <string name="permission_warning_template" msgid="2247087781222679458">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
+ <string name="permission_add_background_warning_template" msgid="1812914855915092273">"Luôn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; <xliff:g id="ACTION">%2$s</xliff:g>?"</string>
<string name="allow_permission_foreground_only" msgid="116465816039675404">"Chỉ khi dùng ứng dụng"</string>
<string name="allow_permission_always" msgid="5194342531206054051">"Luôn luôn"</string>
<string name="deny_permission_deny_and_dont_ask_again" msgid="6106035221490102341">"Không cho phép và không hỏi lại"</string>
@@ -130,7 +130,7 @@
<string name="perm_usage_adv_info_title" msgid="3357831829538873708">"Xem các quyền khác"</string>
<string name="perm_usage_adv_info_summary_2_items" msgid="3702175198750127822">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g>"</string>
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>, <xliff:g id="PERMGROUP_1">%2$s</xliff:g> và <xliff:g id="NUM">%3$s</xliff:g> mục khác"</string>
- <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Lịch trình các ứng dụng dùng <xliff:g id="PERMGROUP">%1$s</xliff:g> của bạn trong 24 giờ qua"</string>
+ <string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"Mốc thời gian các ứng dụng dùng <xliff:g id="PERMGROUP">%1$s</xliff:g> của bạn trong 24 giờ qua"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"Lịch trình các ứng dụng dùng <xliff:g id="PERMGROUP">%1$s</xliff:g> của bạn trong 7 ngày qua"</string>
<string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"Thời điểm ứng dụng này sử dụng quyền <xliff:g id="PERMGROUP">%1$s</xliff:g> của bạn"</string>
<string name="permission_usage_access_dialog_learn_more" msgid="7121468469493184613">"Tìm hiểu thêm"</string>
@@ -201,7 +201,7 @@
<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">"Chế độ cài đặt cho ứng dụng không dùng đến"</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="auto_revoke_label" msgid="5068393642936571656">"Thu hồi quyền nếu bạn 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>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"Tạm dừng hoạt động trong ứng dụng nếu không dùng"</string>
<string name="unused_apps_summary" msgid="8839466950318403115">"Loại bỏ quyền, xoá tệp tạm thời và dừng thông báo"</string>
@@ -221,7 +221,7 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"Ứng dụng không dùng đến"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"Nếu một ứng dụng không được dùng đến trong vài tháng, hệ thống sẽ:\n\n• Thu hồi các quyền để bảo vệ dữ liệu của bạn\n• Chặn các thông báo để tiết kiệm pin\n• Xóa các tệp tạm thời để giải phóng bộ nhớ\n\nĐể cho phép lại các quyền và thông báo, hãy mở ứng dụng đó."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Nếu bạn không dùng một ứng dụng trong một tháng, thì hệ thống sẽ:\n\n• Xoá các quyền để bảo vệ dữ liệu của bạn\n• Xoá các tệp tạm thời để giải phóng dung lượng\n\nĐể cấp lại các quyền, hãy mở ứng dụng đó."</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Lần mở gần đây nhất là hơn # tháng trước}other{Lần mở gần đây nhất là hơn # tháng trước}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Không dùng trong hơn # tháng}other{Không dùng trong hơn # tháng}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"Lần gần đây nhất bạn mở ứng dụng này là vào <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"Lần mở gần đây nhất là vào <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Nếu bạn cho phép quản lý tất cả các tệp, thì ứng dụng này có thể truy cập, sửa đổi và xóa bất kỳ tệp nào trong bộ nhớ chung trên thiết bị này hoặc các thiết bị lưu trữ được kết nối. Ứng dụng có thể truy cập vào tệp mà không cần hỏi bạn."</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Hiển thị tính năng phát hiện trình kích hoạt Trợ lý"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Hiển thị biểu tượng trong thanh trạng thái khi sử dụng micrô để kích hoạt trợ lý thoại"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào ảnh và nội dung nghe nhìn trên thiết bị?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào danh bạ của bạn?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào thông tin vị trí của thiết bị này?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Ứng dụng này sẽ chỉ có quyền truy cập vào vị trí khi bạn đang sử dụng ứng dụng này"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào thông tin vị trí của thiết bị này?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Ứng dụng này có thể muốn truy cập vào thông tin vị trí của bạn mọi lúc, ngay cả khi bạn không dùng ứng dụng. "<annotation id="link">"Hãy cho phép trong phần cài đặt."</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Thay đổi quyền truy cập vào thông tin vị trí đối với &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Ứng dụng này muốn truy cập vào thông tin vị trí của bạn mọi lúc, ngay cả khi bạn không dùng ứng dụng. "<annotation id="link">"Hãy cho phép trong phần cài đặt."</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tìm, kết nối và xác định vị trí tương đối của các thiết bị ở gần?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tìm, kết nối và xác định vị trí tương đối của các thiết bị ở gần? "<annotation id="link">"Bạn có thể cho phép việc này trong phần cài đặt."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Thay đổi quyền truy cập thông tin vị trí của <xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> từ vị trí gần đúng thành vị trí chính xác?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào thông tin vị trí gần đúng của thiết bị này?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Chính xác"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Gần đúng"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào lịch của bạn?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gửi và xem tin nhắn SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào ảnh, nội dung nghe nhìn và tệp trên thiết bị của bạn?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào &lt;b&gt;ảnh, video, nhạc và âm thanh&lt;/b&gt; trên thiết bị này?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào &lt;b&gt;ảnh, video, nhạc, âm thanh và các tệp khác&lt;/b&gt; trên thiết bị này?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào nhạc và âm thanh trên thiết bị này?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào ảnh và video trên thiết bị này?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào ảnh và video khác trên thiết bị này?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ghi âm?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Ứng dụng này chỉ có thể ghi âm khi bạn đang dùng ứng dụng"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ghi âm?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Ứng dụng này có thể muốn ghi âm 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_microphone" msgid="1362781696161233341">"Thay đổi quyền sử dụng micrô của &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Ứng dụng này muốn ghi âm 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="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Bạn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; truy cập vào hoạt động thể chất?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chụp ảnh và quay video?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Ứng dụng này chỉ có thể chụp ảnh và quay video khi bạn đang dùng ứng dụng"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chụp ảnh và quay video?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Ứng dụng này có thể muốn chụp ảnh và quay video 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_camera" msgid="640758449200241582">"Thay đổi quyền sử dụng máy ảnh của &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Ứng dụng này muốn chụp ảnh và quay video 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="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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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 sinh tồn của bạn 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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Để 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 đang không dùng ứng dụng, "<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="auto_granted_permissions" msgid="6009452264824455892">"Các quyền bị kiểm soát"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Các quyền bị kiểm soát"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> có quyền truy cập thông tin vị trí"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Tổ chức của bạn cho phép <xliff:g id="APP_NAME">%1$s</xliff:g> truy cập thông tin vị trí của bạn"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Quyền khác"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Quyền mà hệ thống sử dụng"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Quyền mà chỉ có ứng dụng hệ thống sử dụng."</string>
@@ -519,7 +571,7 @@
<string name="blocked_camera_title" msgid="1128510551791284384">"Quyền truy cập vào máy ảnh của thiết bị đã bị chặn"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"Quyền truy cập vào micrô của thiết bị đã bị chặn"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"Tuỳ chọn vị trí thiết bị đang tắt"</string>
- <string name="blocked_sensor_summary" msgid="4443707628305027375">"Đối với các ứng dụng và dịch vụ"</string>
+ <string name="blocked_sensor_summary" msgid="4443707628305027375">"Áp dụng cho các ứng dụng và dịch vụ"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"Dữ liệu thu được qua micrô vẫn có thể được chia sẻ khi bạn gọi đến số khẩn cấp."</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"Thay đổi"</string>
<string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"Bảo mật và quyền riêng tư"</string>
@@ -537,8 +589,8 @@
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"Kiểm tra trạng thái"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"Các chế độ kiểm soát quyền riêng tư"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"Tùy chọn cài đặt khác"</string>
- <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Truy cập máy ảnh"</string>
- <string name="microphone_toggle_label_qs" msgid="8132912469813396552">"Truy cập micrô"</string>
+ <string name="camera_toggle_label_qs" msgid="3880261453066157285">"Quyền truy cập máy ảnh"</string>
+ <string name="microphone_toggle_label_qs" msgid="8132912469813396552">"Quyền truy cập micrô"</string>
<string name="permissions_removed_qs" msgid="8957319130625294572">"Đã thu hồi quyền sử dụng"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"Xem mức sử dụng của máy ảnh gần đây"</string>
<string name="microphone_usage_qs" msgid="8527666682168170417">"Xem mức sử dụng của micrô gần đây"</string>
@@ -577,20 +629,21 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Xem lại ứng dụng có quyền truy cập thông tin vị trí ở chế độ nền"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Ứng dụng này luôn truy cập được vào thông tin vị trí của bạn, kể cả khi đang đóng.\n\nMột số ứng dụng khẩn cấp và an toàn cần truy cập vào thông tin vị trí của bạn ở chế độ nền để hoạt động như mong đợi."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Đã thay đổi quyền truy cập"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Xem thông tin gần đây về việc sử dụng thông tin vị trí"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Xem thông tin về hoạt động sử dụng thông tin vị trí gần đây"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Chế độ kiểm soát quyền riêng tư"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Quyền truy cập máy ảnh"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Quyền truy cập micrô"</string>
- <string name="perm_toggle_description" msgid="7801326363741451379">"Đối với các ứng dụng và dịch vụ"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"Đối với các ứng dụng và dịch vụ. Nếu chế độ cài đặt này tắt, dữ liệu thu được qua micrô vẫn có thể được chia sẻ khi bạn gọi đến số khẩn cấp."</string>
+ <string name="perm_toggle_description" msgid="7801326363741451379">"Áp dụng cho các ứng dụng và dịch vụ"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"Áp dụng cho các ứng dụng và dịch vụ. Nếu bạn tắt chế độ cài đặt, dữ liệu thu được qua micrô vẫn có thể được chia sẻ khi bạn gọi đến số khẩn cấp."</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"Xem các ứng dụng và dịch vụ có quyền truy cập vào thông tin vị trí của thiết bị"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"Hiện quyền truy cập vào bảng nhớ tạm"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"Hiện thông báo khi có ứng dụng truy cập vào văn bản, hình ảnh hoặc nội dung khác mà bạn đã sao chép"</string>
- <string name="show_password_title" msgid="2877269286984684659">"Hiển thị mật khẩu"</string>
- <string name="show_password_summary" msgid="1110166488865981610">"Hiển thị các ký tự ngắn gọn khi bạn nhập"</string>
+ <string name="show_password_title" msgid="2877269286984684659">"Hiện mật khẩu"</string>
+ <string name="show_password_summary" msgid="1110166488865981610">"Hiện các ký tự trong thời gian ngắn khi bạn nhập"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Nhà phát triển nêu rõ ứng dụng này có thể chia sẻ dữ liệu vị trí với bên thứ ba"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Chia sẻ dữ liệu và thông tin vị trí"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Nguồn cung cấp thông tin về cách thức chia sẻ dữ liệu"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Nhà phát triển đã cung cấp cho nhà sản xuất thiết bị này thông tin về cách thức ứng dụng này chia sẻ dữ liệu. Nhà phát triển có thể cập nhật thông tin này theo thời gian."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Nhà phát triển đã cung cấp thông tin cho "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" về cách thức ứng dụng này chia sẻ dữ liệu. Nhà phát triển có thể cập nhật thông tin này theo thời gian."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Ứng dụng này có thể chia sẻ dữ liệu vị trí cho:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Nhiều cách thức chia sẻ dữ liệu"</string>
@@ -608,12 +661,10 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"An toàn dữ liệu"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Dữ liệu vị trí có thể được chia sẻ"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Nhà phát triển nêu rõ rằng ứng dụng này có thể chia sẻ dữ liệu vị trí với bên thứ ba"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Không mở được đường liên kết này"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Nội dung cập nhật về cách thức chia sẻ dữ liệu vị trí"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Xem xét những ứng dụng đã thay đổi cách thức có thể được dùng để chia sẻ dữ liệu vị trí của bạn"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Những ứng dụng này đã thay đổi cách thức có thể được dùng để chia sẻ dữ liệu vị trí của bạn. Có thể những ứng dụng này trước đây chưa từng chia sẻ dữ liệu vị trí, nhưng bây giờ mới chia sẻ dữ liệu đó nhằm mục đích quảng cáo hoặc tiếp thị."</string>
- <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Nhà phát triển của những ứng dụng này đã cung cấp thông tin cho cửa hàng ứng dụng về cách thức ứng dụng của họ chia sẻ dữ liệu. Họ có thể cập nhật thông tin này theo thời gian.\n\nCách thức chia sẻ dữ liệu có thể thay đổi tuỳ theo phiên bản ứng dụng, cách sử dụng, khu vực và độ tuổi của bạn."</string>
+ <string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Nhà phát triển của những ứng dụng này đã cung cấp thông tin cho một cửa hàng ứng dụng về cách thức ứng dụng của họ chia sẻ dữ liệu. Họ có thể cập nhật thông tin này theo thời gian.\n\nCách thức chia sẻ dữ liệu có thể thay đổi tuỳ theo phiên bản ứng dụng, cách sử dụng, khu vực và độ tuổi của bạn."</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"Tìm hiểu về chế độ chia sẻ dữ liệu"</string>
<string name="shares_location_with_third_parties" msgid="2278051743742057767">"Dữ liệu vị trí của bạn nay được chia sẻ với bên thứ ba"</string>
<string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"Dữ liệu vị trí của bạn giờ đây được chia sẻ với các bên thứ ba để quảng cáo hoặc tiếp thị"</string>
diff --git a/PermissionController/res/values-w764dp-v33/layout.xml b/PermissionController/res/values-w764dp-v33/layout.xml
new file mode 100644
index 000000000..9035c8868
--- /dev/null
+++ b/PermissionController/res/values-w764dp-v33/layout.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="action_button_list_responsive" type="layout">
+ @layout/action_button_list_large_screen
+ </item>
+</resources> \ No newline at end of file
diff --git a/PermissionController/res/values-w764dp-v33/styles.xml b/PermissionController/res/values-w764dp-v33/styles.xml
index a836e4aa5..78f1bb42e 100644
--- a/PermissionController/res/values-w764dp-v33/styles.xml
+++ b/PermissionController/res/values-w764dp-v33/styles.xml
@@ -16,6 +16,16 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="SafetyCenterActionButton.Responsive">
+ <item name="android:paddingStart">@dimen/sc_button_horizontal_padding_large_screen</item>
+ <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding_large_screen</item>
+ </style>
+
+ <style name="SecondarySafetyCenterActionButton.Responsive">
+ <item name="android:paddingStart">@dimen/sc_button_horizontal_padding_large_screen</item>
+ <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding_large_screen</item>
+ </style>
+
<!-- START SAFETY STATUS CARD -->
<style name="SafetyCenterStatusTitleAndSummaryContainer.Responsive">
<item name="layout_constraintEnd_toStartOf">@id/sc_status_buttons_start_barrier</item>
@@ -30,8 +40,8 @@
<item name="layout_constraintStart_toEndOf">@id/status_title_and_summary</item>
<item name="layout_constraintEnd_toEndOf">parent</item>
<item name="android:layout_marginTop">@dimen/sc_spacing_xxsmall</item>
- <item name="android:paddingStart">@dimen/sc_large_screen_button_padding</item>
- <item name="android:paddingEnd">@dimen/sc_large_screen_button_padding</item>
+ <item name="android:paddingStart">@dimen/sc_button_horizontal_padding_large_screen</item>
+ <item name="android:paddingEnd">@dimen/sc_button_horizontal_padding_large_screen</item>
<!-- Clear the base style constraints so they don't conflict with this style's constraints
on the same sides. -->
<item name="layout_constraintTop_toBottomOf">@null</item>
diff --git a/PermissionController/res/values-watch/themes.xml b/PermissionController/res/values-watch/themes.xml
index 0e9b7a919..6240a8d07 100644
--- a/PermissionController/res/values-watch/themes.xml
+++ b/PermissionController/res/values-watch/themes.xml
@@ -21,6 +21,8 @@
<style name="Theme.PermissionController.Settings" parent="Settings" />
<style name="GrantPermissions" parent="@android:style/Theme.DeviceDefault.NoActionBar">
- <item name="android:windowBackground">@android:color/transparent</item>
</style>
+
+ <style name="Theme.PermissionController.IncidentReportDialog"
+ parent="@android:style/Theme.DeviceDefault.Dialog.Alert" />
</resources>
diff --git a/PermissionController/res/values-zh-rCN-v33/strings.xml b/PermissionController/res/values-zh-rCN-v33/strings.xml
index 0e4242912..064e8b581 100644
--- a/PermissionController/res/values-zh-rCN-v33/strings.xml
+++ b/PermissionController/res/values-zh-rCN-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"更多提醒"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"忽略的提醒"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{展开并查看另外一项提醒}other{展开并查看另外 # 项提醒}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"提醒:<xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"操作完成"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"查看可提高设备安全性的设置"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"“安全和隐私”快捷设置"</string>
diff --git a/PermissionController/res/values-zh-rCN/strings.xml b/PermissionController/res/values-zh-rCN/strings.xml
index a87874676..06e82410d 100644
--- a/PermissionController/res/values-zh-rCN/strings.xml
+++ b/PermissionController/res/values-zh-rCN/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"始终全部允许"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"选择照片和视频"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"选择更多"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"不选择更多数据"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"不选择其他数据"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"仍然不允许"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"关闭"</string>
<string name="current_permission_template" msgid="7452035392573329375">"第 <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> 项权限(共 <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> 项)"</string>
@@ -59,8 +59,8 @@
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"允许访问媒体文件"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"应用"</string>
<string name="app_permissions" msgid="3369917736607944781">"应用权限"</string>
- <string name="unused_apps" msgid="2058057455175955094">"未使用的应用"</string>
- <string name="no_unused_apps" msgid="12809387670415295">"没有未使用的应用"</string>
+ <string name="unused_apps" msgid="2058057455175955094">"闲置应用"</string>
+ <string name="no_unused_apps" msgid="12809387670415295">"无闲置应用"</string>
<string name="zero_unused_apps" msgid="9024448554157499748">"没有未使用的应用"</string>
<string name="review_permission_decisions" msgid="309559429150613632">"最近的权限决定"</string>
<string name="review_permission_decisions_view_all" msgid="90391040431566130">"查看最近的所有权限决定"</string>
@@ -196,14 +196,14 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"使用确切位置"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"确切位置关闭时,应用可以获取您的大致位置"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>权限"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"是否允许这个应用访问<xliff:g id="PERM">%1$s</xliff:g>"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"是否允许此应用获得“<xliff:g id="PERM">%1$s</xliff:g>”权限"</string>
<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="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_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>
@@ -218,7 +218,7 @@
<string name="auto_revoked_app_summary_one" msgid="7093213590301252970">"已移除<xliff:g id="PERMISSION_NAME">%s</xliff:g>权限"</string>
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"已移除<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g>以及<xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g>权限"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"已移除<xliff:g id="PERMISSION_NAME">%1$s</xliff:g>权限及另外 <xliff:g id="NUMBER">%2$s</xliff:g> 项权限"</string>
- <string name="unused_apps_page_title" msgid="6986983535677572559">"未使用的应用"</string>
+ <string name="unused_apps_page_title" msgid="6986983535677572559">"闲置应用"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"如果您连续几个月未使用某个应用,系统将对该应用采取以下措施:\n\n• 移除权限以保护您的数据\n• 停止通知功能以节省电量\n• 移除临时文件以释放空间\n\n如需重新授予权限以继续接收通知,请打开该应用。"</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"如果您连续 1 个月未使用某个应用,系统将对该应用采取以下措施:\n\n• 撤消权限以保护您的数据\n• 移除临时文件以释放空间\n\n如需重新授予权限,请打开该应用。"</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{距上次打开已超过 # 个月}other{距上次打开已超过 # 个月}}"</string>
@@ -233,7 +233,7 @@
<string name="permission_description_summary_camera" msgid="108004375101882069">"具有此权限的应用可以拍摄照片和录制视频"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"具有此权限的应用可以访问您的通讯录"</string>
<string name="permission_description_summary_location" msgid="2817531799933480694">"具有此权限的应用可以使用此设备的位置信息"</string>
- <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"具有这项权限的应用可以查找、连接附近设备以及确定附近设备的相对位置"</string>
+ <string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"具有这项权限的应用可以查找、连接附近设备,以及确定附近设备的相对位置"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"具有此权限的应用可以录制音频"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"具有此权限的应用可以拨打电话及管理通话"</string>
<string name="permission_description_summary_sensors" msgid="1836045815643119949">"具有此权限的应用可以获取与您的生命体征相关的传感器数据"</string>
@@ -302,7 +302,7 @@
<string name="auto_revoke_before_notification_title_one" msgid="6758024954464359876">"1 个应用未使用"</string>
<string name="auto_revoke_before_notification_title_many" msgid="4415543943846385685">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> 个应用未使用"</string>
<string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"为保护您的隐私,系统将移除这些权限。点按即可查看。"</string>
- <string name="unused_apps_title" msgid="8589298917717872239">"未使用的应用"</string>
+ <string name="unused_apps_title" msgid="8589298917717872239">"闲置应用"</string>
<string name="unused_apps_subtitle_after" msgid="2034267519506357898">"以下应用的权限已被移除"</string>
<string name="unused_apps_subtitle_before" msgid="5233302577076132427">"以下应用的权限将被移除"</string>
<string name="unused_permissions_subtitle_two" msgid="2207266295008423015">"“<xliff:g id="PERM_NAME_0">%1$s</xliff:g>”权限和“<xliff:g id="PERM_NAME_1">%2$s</xliff:g>”权限"</string>
@@ -455,59 +455,111 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"显示智能助理应用触发检测"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"使用麦克风激活语音助理后,在状态栏中显示相关图标"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您设备上的照片和媒体吗?"</string>
- <string name="permgrouprequest_contacts" msgid="8391550064551053695">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您的通讯录吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
+ <string name="permgrouprequest_contacts" msgid="8391550064551053695">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”访问您的通讯录吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”获取此设备的位置信息吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"只有当您使用该应用时,该应用才有权访问位置信息"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”获取此设备的位置信息吗?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"该应用可能想要随时获取您的位置信息(即使您并未使用该应用)。"<annotation id="link">"在“设置”中允许"</annotation>"。"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"要更改&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;的位置信息访问权限吗?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"该应用想要随时获取您的位置信息(即使您并未使用该应用)。"<annotation id="link">"在“设置”中允许"</annotation>"。"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”查找、连接到附近设备以及确定附近设备的相对位置吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;查找、连接附近设备以及确定附近设备的相对位置吗?"<annotation id="link">"您可以在“设置”中允许。"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"要将“<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>”可以使用的位置信息从大致位置改为确切位置吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”获取此设备的大致位置信息吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"确切位置"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"大致位置"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问您的日历吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;发送和查看短信吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"要允许“<xliff:g id="APP_NAME">%1$s</xliff:g>”&lt;b&gt;&lt;/b&gt;访问您设备上的照片、媒体内容和文件吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”访问此设备上的&lt;b&gt;照片、视频、音乐和音频&lt;/b&gt;吗?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”访问此设备上的&lt;b&gt;照片、视频、音乐、音频和其他文件&lt;/b&gt;吗?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问此设备上的音乐和音频吗?"</string>
- <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问此设备上的照片和视频吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
+ <string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”访问此设备上的照片和视频吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问此设备上的更多照片和视频?"</string>
- <string name="permgrouprequest_microphone" msgid="2825208549114811299">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;录音吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
+ <string name="permgrouprequest_microphone" msgid="2825208549114811299">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”录音吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"此应用将只能在您使用它时录音"</string>
- <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"要允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;录音吗?"</string>
+ <string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”录音吗?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"此应用可能想要随时录音,即使在您未使用它的时候。"<annotation id="link">"您可以在“设置”中授权"</annotation>"。"</string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"要更改&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;的麦克风使用权限吗?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"此应用想要随时录音,即使在您未使用它的时候。"<annotation id="link">"您可以在“设置”中授权"</annotation>"。"</string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;获取您的身体活动数据吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”拍摄照片和录制视频吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"此应用将只能在您使用它时拍摄照片和录制视频"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”拍摄照片和录制视频吗?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"此应用可能想要随时拍摄照片和录制视频,即使在您未使用它的时候。"<annotation id="link">"您可以在“设置”中授权"</annotation>"。"</string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"要更改&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;的相机使用权限吗?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"此应用想要随时拍摄照片和录制视频,即使在您未使用它的时候。"<annotation id="link">"您可以在“设置”中授权"</annotation>"。"</string>
- <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_calllog" msgid="2065327180175371397">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”访问您的手机通话记录吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
+ <string name="permgrouprequest_phone" msgid="1829234136997316752">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”拨打电话和管理通话吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;访问与您的生命体征相关的传感器数据吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"如要允许此应用始终可以访问身体传感器数据(即使在您未使用此应用时),请"<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="auto_granted_permissions" msgid="6009452264824455892">"受控权限"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"要允许“&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;”向您发送通知吗?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"受控权限"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"<xliff:g id="APP_NAME">%1$s</xliff:g> 具有位置信息访问权限"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"您的组织允许 <xliff:g id="APP_NAME">%1$s</xliff:g> 访问位置信息"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"其他权限"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"系统使用的权限"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"仅限系统应用使用的权限"</string>
<string name="additional_permissions_label" msgid="7693557637462569046">"其他权限"</string>
<string name="additional_permissions_description" msgid="2186611950890732112">"应用定义的权限"</string>
- <string name="privdash_label_camera" msgid="1426440033626198096">"摄像头"</string>
+ <string name="privdash_label_camera" msgid="1426440033626198096">"相机"</string>
<string name="privdash_label_microphone" msgid="8415035835803511693">"麦克风"</string>
<string name="privdash_label_location" msgid="6882400763866489291">"位置信息"</string>
<string name="privdash_label_other" msgid="3710394147423236033">"其他"</string>
@@ -515,7 +567,7 @@
<string name="privdash_label_24h" msgid="1512532123865375319">"过去 24 小时\n"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"过去\n7 天"</string>
<string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理,因此状态栏或隐私信息中心不会显示这个应用的权限使用情况。"</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理,因此隐私信息中心不会显示这个应用的权限使用情况。"</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”受 Android 保护。由于您的数据是在此设备上处理的,因此隐私信息中心不会显示该应用的权限使用情况。"</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"设备摄像头已被屏蔽"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"设备麦克风已被屏蔽"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"设备位置信息功能已关闭"</string>
@@ -537,7 +589,7 @@
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"查看状态"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"您的隐私控制项"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"更多设置"</string>
- <string name="camera_toggle_label_qs" msgid="3880261453066157285">"相机使用权限"</string>
+ <string name="camera_toggle_label_qs" msgid="3880261453066157285">"摄像头使用权限"</string>
<string name="microphone_toggle_label_qs" msgid="8132912469813396552">"麦克风使用权限"</string>
<string name="permissions_removed_qs" msgid="8957319130625294572">"已移除权限"</string>
<string name="camera_usage_qs" msgid="4394233566086665994">"查看近期相机使用情况"</string>
@@ -588,9 +640,10 @@
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"系统会在应用访问您复制的文字、图片或其他内容时显示一条消息"</string>
<string name="show_password_title" msgid="2877269286984684659">"显示密码"</string>
<string name="show_password_summary" msgid="1110166488865981610">"输入时短暂显示字符"</string>
- <string name="permission_rationale_message_location" msgid="2153841534298068414">"此应用已声明它可能会与第三方共享位置数据"</string>
+ <string name="permission_rationale_message_location" msgid="2153841534298068414">"此应用已声明它可能会与第三方分享位置数据"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"数据分享和位置信息"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"数据分享信息的来源"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"开发者已将此应用的数据分享方式相关信息提供给此设备的制造商。开发者可能会随时间推移更新此信息。"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"开发者已将此应用的数据分享方式相关信息提供给"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"。开发者可能会随时间推移更新此信息。"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"此应用可能会出于以下目的分享位置数据:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"数据分享因情况而异"</string>
@@ -604,12 +657,10 @@
<string name="permission_rationale_purpose_advertising" msgid="7156966429245180236">"广告或营销"</string>
<string name="permission_rationale_purpose_fraud_prevention_security" msgid="4262104770357031902">"欺诈防范、安全和法规遵从"</string>
<string name="permission_rationale_purpose_personalization" msgid="1589973273682238708">"个性化"</string>
- <string name="permission_rationale_purpose_account_management" msgid="2985772421946688879">"帐号管理"</string>
+ <string name="permission_rationale_purpose_account_management" msgid="2985772421946688879">"账号管理"</string>
<string name="app_permission_rationale_message" msgid="8511466916077100713">"数据安全"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"可能会分享位置数据"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"此应用已声明它可能会与第三方分享您的位置数据"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"无法打开此链接"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"位置数据分享方面的更新"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"查看改变了位置数据分享方式的应用"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"这些应用改变了它们在分享您位置数据上的做法。它们之前可能未分享过位置数据,也可能现在是为了广告或营销目的而分享此类数据。"</string>
diff --git a/PermissionController/res/values-zh-rHK-car/strings.xml b/PermissionController/res/values-zh-rHK-car/strings.xml
index fae91ec10..1c9959056 100644
--- a/PermissionController/res/values-zh-rHK-car/strings.xml
+++ b/PermissionController/res/values-zh-rHK-car/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="unused_apps_page_summary" msgid="7505839764289846511">"如果您在過去幾個月未曾使用應用程式,系統將會:\n\n• 移除權限以保護您的資料\n• 移除暫存檔案以騰出空間"</string>
+ <string name="unused_apps_page_summary" msgid="7505839764289846511">"如果你在過去幾個月未曾使用應用程式,系統將會:\n\n• 移除權限以保護你的資料\n• 移除暫存檔案以騰出空間"</string>
</resources>
diff --git a/PermissionController/res/values-zh-rHK-television/strings.xml b/PermissionController/res/values-zh-rHK-television/strings.xml
index dd90168f9..4a8a23848 100644
--- a/PermissionController/res/values-zh-rHK-television/strings.xml
+++ b/PermissionController/res/values-zh-rHK-television/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="grant_dialog_button_deny_dont_ask_again" msgid="747769682501286250">"拒絕,不要再詢問"</string>
- <string name="grant_dialog_how_to_change" msgid="997462845048160559">"您稍後可以在 [設定] &gt; [應用程式] 中變更這項設定"</string>
+ <string name="grant_dialog_how_to_change" msgid="997462845048160559">"你稍後可以在 [設定] &gt; [應用程式] 中變更這項設定"</string>
<string name="current_permission_template" msgid="6240787325714651204">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string>
<string name="preference_show_system_apps" msgid="4262140518693221093">"顯示系統應用程式"</string>
<string name="app_permissions_decor_title" msgid="7438716722786036814">"應用程式權限"</string>
diff --git a/PermissionController/res/values-zh-rHK-v33/strings.xml b/PermissionController/res/values-zh-rHK-v33/strings.xml
index 27174dbb3..da31b6eae 100644
--- a/PermissionController/res/values-zh-rHK-v33/strings.xml
+++ b/PermissionController/res/values-zh-rHK-v33/strings.xml
@@ -16,10 +16,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="role_dialer_request_description" msgid="6188305064871543419">"此應用程式將可傳送通知,並能存取您的相機、通訊錄、麥克風、電話及短訊"</string>
- <string name="role_sms_request_description" msgid="1506966389698625395">"此應用程式將可傳送通知,並能存取您的相機、通訊錄、檔案、麥克風、電話及短訊"</string>
+ <string name="role_dialer_request_description" msgid="6188305064871543419">"此應用程式將可傳送通知,並能存取你的相機、通訊錄、麥克風、電話及短訊"</string>
+ <string name="role_sms_request_description" msgid="1506966389698625395">"此應用程式將可傳送通知,並能存取你的相機、通訊錄、檔案、麥克風、電話及短訊"</string>
<string name="permission_description_summary_storage" msgid="1917071243213043858">"擁有此權限的應用程式可存取此裝置上的所有檔案"</string>
- <string name="work_policy_title" msgid="832967780713677409">"您的工作政策資料"</string>
+ <string name="work_policy_title" msgid="832967780713677409">"你的工作政策資料"</string>
<string name="work_policy_summary" msgid="3886113358084963931">"由 IT 管理員管理的設定"</string>
<string name="safety_center_entry_group_expand_action" msgid="5358289574941779652">"展開並顯示清單"</string>
<string name="safety_center_entry_group_collapse_action" msgid="1525710152244405656">"收合清單並隱藏設定"</string>
diff --git a/PermissionController/res/values-zh-rHK-v34/strings.xml b/PermissionController/res/values-zh-rHK-v34/strings.xml
index 99e078541..65ad05bdb 100644
--- a/PermissionController/res/values-zh-rHK-v34/strings.xml
+++ b/PermissionController/res/values-zh-rHK-v34/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="security_privacy_brand_name" msgid="7303621734258440812">"安全性和私隱權"</string>
+ <string name="security_privacy_brand_name" msgid="7303621734258440812">"保安和私隱"</string>
<string name="privacy_subpage_controls_header" msgid="4152396976713749322">"控制項"</string>
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"管理應用程式的健康資料存取權"</string>
diff --git a/PermissionController/res/values-zh-rHK/strings.xml b/PermissionController/res/values-zh-rHK/strings.xml
index f2546c69c..6cff2067c 100644
--- a/PermissionController/res/values-zh-rHK/strings.xml
+++ b/PermissionController/res/values-zh-rHK/strings.xml
@@ -36,7 +36,7 @@
<string name="grant_dialog_button_always_allow_all" msgid="1719900027660252167">"一律全部允許"</string>
<string name="grant_dialog_button_allow_selected_photos" msgid="5497042471576153842">"選取相片和影片"</string>
<string name="grant_dialog_button_allow_more_selected_photos" msgid="5145657877588697709">"選取更多項目"</string>
- <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"不選取更多資料"</string>
+ <string name="grant_dialog_button_dont_select_more" msgid="6643552729129461268">"不選取更多"</string>
<string name="grant_dialog_button_deny_anyway" msgid="7225905870668915151">"一律不允許"</string>
<string name="grant_dialog_button_dismiss" msgid="1930399742250226393">"關閉"</string>
<string name="current_permission_template" msgid="7452035392573329375">"第 <xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> 個 (共 <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g> 個)"</string>
@@ -66,11 +66,11 @@
<string name="review_permission_decisions_view_all" msgid="90391040431566130">"查看所有最近的權限決定"</string>
<string name="review_permission_decisions_empty" msgid="8120775336417279806">"最近沒有權限決定"</string>
<string name="auto_permission_manager_summary" msgid="9157438376234301354">"管理日曆、通話記錄等項目的資料存取權"</string>
- <string name="granted_permission_decision" msgid="7824827491551861365">"您已允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取<xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
- <string name="denied_permission_decision" msgid="5308961501779563781">"您已拒絕「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取<xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
+ <string name="granted_permission_decision" msgid="7824827491551861365">"你已允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取<xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
+ <string name="denied_permission_decision" msgid="5308961501779563781">"你已拒絕「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取<xliff:g id="PERMISSION_NAME">%2$s</xliff:g>"</string>
<string name="days_ago" msgid="6650359081551335629">"{count,plural, =0{今天}=1{1 天前}other{# 天前}}"</string>
<string name="app_disable_dlg_positive" msgid="7418444149981904940">"停用應用程式"</string>
- <string name="app_disable_dlg_text" msgid="3126943217146120240">"如果您停用此應用程式,Android 和其他應用程式可能無法正常運作。請謹記,由於此應用程式已在您的裝置預先安裝,因此無法刪除。停用後,您便可在裝置上關閉並隱藏此應用程式。"</string>
+ <string name="app_disable_dlg_text" msgid="3126943217146120240">"如果你停用此應用程式,Android 和其他應用程式可能無法正常運作。請謹記,由於此應用程式已在你的裝置預先安裝,因此無法刪除。停用後,你便可在裝置上關閉並隱藏此應用程式。"</string>
<string name="app_permission_manager" msgid="3903811137630909550">"權限管理工具"</string>
<string name="never_ask_again" msgid="4728762438198560329">"不要再詢問"</string>
<string name="no_permissions" msgid="3881676756371148563">"沒有權限"</string>
@@ -90,11 +90,11 @@
<string name="manage_permission" msgid="2895385393037061964">"管理權限"</string>
<string name="no_apps" msgid="2412612731628386816">"沒有應用程式"</string>
<string name="location_settings" msgid="3624412509133422562">"位置設定"</string>
- <string name="location_warning" msgid="2381649060929040962">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為此裝置提供定位服務。您可以在位置設定中更改位置存取權。"</string>
- <string name="system_warning" msgid="1173400963234358816">"如果您拒絕授予此權限,裝置的基本功能或會無法正常運作。"</string>
+ <string name="location_warning" msgid="2381649060929040962">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為此裝置提供定位服務。你可以在位置設定中更改位置存取權。"</string>
+ <string name="system_warning" msgid="1173400963234358816">"如果你拒絕授予此權限,裝置的基本功能或會無法正常運作。"</string>
<string name="deny_read_media_visual_warning" msgid="3982586279917232827">"此應用程式專為舊版 Android 而設。如果拒絕此應用程式存取相片和影片,此應用程式亦無法存取音樂和其他音訊。"</string>
<string name="deny_read_media_aural_warning" msgid="8928699919508646732">"此應用程式專為舊版 Android 而設。如果拒絕此應用程式存取音樂和其他音訊,此應用程式亦無法存取相片和影片。"</string>
- <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"如果您拒絕授予此權限,裝置上受此應用程式管理的部分功能可能無法正常運作。"</string>
+ <string name="cdm_profile_revoke_warning" msgid="4443893270719106700">"如果你拒絕授予此權限,裝置上受此應用程式管理的部分功能可能無法正常運作。"</string>
<string name="permission_summary_enforced_by_policy" msgid="4443598170942950519">"已根據政策執行"</string>
<string name="permission_summary_disabled_by_policy_background_only" msgid="221995005556362660">"已根據政策停用背景存取權"</string>
<string name="permission_summary_enabled_by_policy_background_only" msgid="8287675974767104279">"已根據政策啟用背景存取權"</string>
@@ -132,7 +132,7 @@
<string name="perm_usage_adv_info_summary_more_items" msgid="949055326299562218">"<xliff:g id="PERMGROUP_0">%1$s</xliff:g>、<xliff:g id="PERMGROUP_1">%2$s</xliff:g> 和另外 <xliff:g id="NUM">%3$s</xliff:g> 個"</string>
<string name="permission_group_usage_subtitle_24h" msgid="5120155996322114181">"過去 24 小時內應用程式使用「<xliff:g id="PERMGROUP">%1$s</xliff:g>」權限的時間軸"</string>
<string name="permission_group_usage_subtitle_7d" msgid="1465828402260324654">"過去 7 天內應用程式使用「<xliff:g id="PERMGROUP">%1$s</xliff:g>」權限的時間軸"</string>
- <string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"當此應用程式使用您的<xliff:g id="PERMGROUP">%1$s</xliff:g>權限時"</string>
+ <string name="permission_usage_access_dialog_subtitle" msgid="4171772805196955753">"當此應用程式使用你的<xliff:g id="PERMGROUP">%1$s</xliff:g>權限時"</string>
<string name="permission_usage_access_dialog_learn_more" msgid="7121468469493184613">"瞭解詳情"</string>
<string name="learn_more_content_description" msgid="8673699744544502539">"進一步瞭解「<xliff:g id="PERMGROUP">%1$s</xliff:g>」"</string>
<string name="manage_permission_summary" msgid="4117555482684114317">"控制應用程式<xliff:g id="PERMGROUP">%1$s</xliff:g>存取權"</string>
@@ -194,7 +194,7 @@
<string name="precise_image_description" msgid="6349638632303619872">"精確位置"</string>
<string name="approximate_image_description" msgid="938803699637069884">"概略位置"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"使用精確位置"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"關閉精確位置後,應用程式可存取您的概略位置"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"關閉精確位置後,應用程式可存取你的概略位置"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>權限"</string>
<string name="app_permission_header" msgid="2951363137032603806">"這個應用程式的<xliff:g id="PERM">%1$s</xliff:g>存取權"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"查看「<xliff:g id="APP">%1$s</xliff:g>」的所有權限"</string>
@@ -205,9 +205,9 @@
<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>
+ <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>
<string name="auto_revoke_open_app_message" msgid="8075556291711205039">"如要重新授予權限,請開啟應用程式。"</string>
<string name="auto_revoke_disabled" msgid="8697684442991567188">"此應用程式已停用自動移除功能。"</string>
<string name="auto_revocable_permissions_none" msgid="8334929619113991466">"目前沒有授予任何自動撤銷權限"</string>
@@ -219,19 +219,19 @@
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"已移除「<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g>」及「<xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g>」權限"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"已移除「<xliff:g id="PERMISSION_NAME">%1$s</xliff:g>」及另外 <xliff:g id="NUMBER">%2$s</xliff:g> 個權限"</string>
<string name="unused_apps_page_title" msgid="6986983535677572559">"不使用的應用程式"</string>
- <string name="unused_apps_page_summary" msgid="1867593913217272155">"如果應用程式在過去幾個月未曾使用,系統將會:\n\n• 移除權限以保護您的資料\n• 停止顯示通知以節省電量\n• 移除暫存檔案以騰出空間\n\n如要重新允許權限和通知,請開啟應用程式。"</string>
- <string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"如果您在過去一個月未曾使用應用程式,系統將會:\n\n• 移除權限以保護您的資料\n• 移除暫存檔案以騰出空間\n\n如要再次允許權限,請開啟應用程式。"</string>
+ <string name="unused_apps_page_summary" msgid="1867593913217272155">"如果應用程式在過去幾個月未曾使用,系統將會:\n\n• 移除權限以保護你的資料\n• 停止顯示通知以節省電量\n• 移除暫存檔案以騰出空間\n\n如要重新允許權限和通知,請開啟應用程式。"</string>
+ <string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"如果你在過去一個月未曾使用應用程式,系統將會:\n\n• 移除權限以保護你的資料\n• 移除暫存檔案以騰出空間\n\n如要再次允許權限,請開啟應用程式。"</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{距離上次開啟已超過 # 個月}other{距離上次開啟已超過 # 個月}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"應用程式上次於 <xliff:g id="DATE">%s</xliff:g>開啟"</string>
<string name="last_opened_summary_short" msgid="1646067226191176825">"上次開啟日期:<xliff:g id="DATE">%s</xliff:g>"</string>
- <string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"如允許管理所有檔案,此應用程式便可存取、修改和刪除此裝置或已連接儲存裝置上一般儲存的任何檔案。應用程式可能會在未通知您的情況下存取檔案。"</string>
- <string name="special_file_access_dialog" msgid="583804114020740610">"要允許此應用程式存取、修改和刪除此裝置或任何已連接儲存裝置上的檔案嗎?此應用程式可能會在未通知您的情況下存取檔案。"</string>
+ <string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"如允許管理所有檔案,此應用程式便可存取、修改和刪除此裝置或已連接儲存裝置上一般儲存的任何檔案。應用程式可能會在未通知你的情況下存取檔案。"</string>
+ <string name="special_file_access_dialog" msgid="583804114020740610">"要允許此應用程式存取、修改和刪除此裝置或任何已連接儲存裝置上的檔案嗎?此應用程式可能會在未通知你的情況下存取檔案。"</string>
<string name="permission_description_summary_generic" msgid="5401399408814903391">"擁有此權限的應用程式可以<xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
- <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"擁有此權限的應用程式可以存取您的體能活動資料,例如步行、踏單車、駕駛、步數及其他資料"</string>
- <string name="permission_description_summary_calendar" msgid="103329982944411010">"擁有此權限的應用程式可以存取您的日曆"</string>
+ <string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"擁有此權限的應用程式可以存取你的體能活動資料,例如步行、踏單車、駕駛、步數及其他資料"</string>
+ <string name="permission_description_summary_calendar" msgid="103329982944411010">"擁有此權限的應用程式可以存取你的日曆"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"擁有此權限的應用程式可以讀取及寫入手機通話記錄"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"擁有此權限的應用程式可以拍照及錄製影片"</string>
- <string name="permission_description_summary_contacts" msgid="2337798886460408996">"擁有此權限的應用程式可以存取您的通訊錄"</string>
+ <string name="permission_description_summary_contacts" msgid="2337798886460408996">"擁有此權限的應用程式可以存取你的通訊錄"</string>
<string name="permission_description_summary_location" msgid="2817531799933480694">"擁有此權限的應用程式可以存取此裝置的位置資訊"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"擁有此權限的應用程式可以尋找和連接附近的裝置,並可判斷附近裝置的相對位置"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"擁有此權限的應用程式可以錄音"</string>
@@ -260,7 +260,7 @@
<string name="permission_reminders" msgid="6528257957664832636">"權限提醒"</string>
<string name="auto_revoke_permission_reminder_notification_title_one" msgid="6690347469376854137">"1 個不使用的應用程式"</string>
<string name="auto_revoke_permission_reminder_notification_title_many" msgid="6062217713645069960">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> 個不使用的應用程式"</string>
- <string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"為保護您的私隱,系統已移除權限。輕按即可查看"</string>
+ <string name="auto_revoke_permission_reminder_notification_content" msgid="4492228990462107487">"為保護你的私隱,系統已移除權限。輕按即可查看"</string>
<string name="auto_revoke_permission_notification_title" msgid="2629844160853454657">"已移除沒有用過的應用程式的權限"</string>
<string name="auto_revoke_permission_notification_content" msgid="5125990886047799375">"部分應用程式在過去幾個月都沒有用過。輕按即可查看。"</string>
<string name="unused_apps_notification_title" msgid="4314832015894238019">"{count,plural, =1{# 個未使用的應用程式}other{# 個未使用的應用程式}}"</string>
@@ -269,28 +269,28 @@
<string name="unused_apps_safety_center_card_content" msgid="1088557243627427820">"如果應用程式已沒有使用一段時間,系統會移除權限和臨時檔案,並停止顯示通知。"</string>
<string name="unused_apps_safety_center_action_title" msgid="8865914432518993194">"查看應用程式"</string>
<string name="post_drive_permission_decision_reminder_title" msgid="1290697371418139976">"查看最近授予的權限"</string>
- <string name="post_drive_permission_decision_reminder_summary_1_app_1_permission" msgid="670521503734140711">"您在駕駛時已將<xliff:g id="PERMISSION">%2$s</xliff:g>的存取權授予「<xliff:g id="APP">%1$s</xliff:g>」"</string>
- <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>
+ <string name="post_drive_permission_decision_reminder_summary_1_app_1_permission" msgid="670521503734140711">"你在駕駛時已將<xliff:g id="PERMISSION">%2$s</xliff:g>的存取權授予「<xliff:g id="APP">%1$s</xliff:g>」"</string>
+ <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>
<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>
<string name="all_unused_apps_category_title" msgid="755663524704745414">"所有沒有用過的應用程式"</string>
<string name="months_ago" msgid="1766026492610646354">"<xliff:g id="COUNT">%1$d</xliff:g> 個月前"</string>
- <string name="auto_revoke_preference_summary" msgid="5517958331781391481">"為保護您的私隱,系統已移除權限"</string>
- <string name="background_location_access_reminder_notification_title" msgid="1140797924301941262">"<xliff:g id="APP_NAME">%s</xliff:g>在背景存取了您的位置資訊"</string>
- <string name="background_location_access_reminder_notification_content" msgid="7787084707336546245">"此應用程式可隨時存取您的位置資訊。輕按即可變更權限。"</string>
+ <string name="auto_revoke_preference_summary" msgid="5517958331781391481">"為保護你的私隱,系統已移除權限"</string>
+ <string name="background_location_access_reminder_notification_title" msgid="1140797924301941262">"<xliff:g id="APP_NAME">%s</xliff:g>在背景存取了你的位置資訊"</string>
+ <string name="background_location_access_reminder_notification_content" msgid="7787084707336546245">"此應用程式可隨時存取你的位置資訊。輕按即可變更權限。"</string>
<string name="notification_listener_reminder_notification_title" msgid="3747210460187479091">"查看擁有通知存取權的應用程式"</string>
<string name="notification_listener_reminder_notification_content" msgid="831476101108863427">"<xliff:g id="APP_NAME">%s</xliff:g> 可關閉通知內容、對內容採取動作以及存取內容"</string>
- <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"此應用程式可讓您關閉/存取通知中的內容或執行操作。有些應用程式需要此權限才能正常運作。"</string>
+ <string name="notification_listener_warning_card_content" msgid="7840973324284115893">"此應用程式可讓你關閉/存取通知中的內容或執行操作。有些應用程式需要此權限才能正常運作。"</string>
<string name="notification_listener_remove_access_button_label" msgid="7101898782417817097">"移除存取權"</string>
<string name="notification_listener_review_app_button_label" msgid="3433073281029143924">"查看更多選項"</string>
<string name="notification_listener_remove_access_success_label" msgid="2477611529875633107">"已移除存取權"</string>
<string name="accessibility_access_reminder_notification_title" msgid="2971317234668807566">"查看擁有完整裝置存取權的應用程式"</string>
<string name="accessibility_access_reminder_notification_content" msgid="7389454158175306720">"「<xliff:g id="APP_NAME">%s</xliff:g>」可以查看裝置畫面並在裝置上執行操作。無障礙應用程式需要取得這種存取權才能發揮功用。"</string>
- <string name="accessibility_access_warning_card_content" msgid="4370327190293217358">"此應用程式可以查看裝置畫面並在裝置上執行操作。無障礙應用程式需要取得這種存取權才能發揮功用,但請確認您信任此應用程式。"</string>
+ <string name="accessibility_access_warning_card_content" msgid="4370327190293217358">"此應用程式可以查看裝置畫面並在裝置上執行操作。無障礙應用程式需要取得這種存取權才能發揮功用,但請確認你信任此應用程式。"</string>
<string name="accessibility_remove_access_button_label" msgid="44145801526711640">"移除存取權"</string>
<string name="accessibility_show_all_apps_button_label" msgid="960067249326392280">"查看擁有完整存取權的應用程式"</string>
<string name="accessibility_remove_access_success_label" msgid="4380995302917014670">"已移除存取權"</string>
@@ -301,14 +301,14 @@
<string name="auto_revoke_after_notification_content_many" msgid="4774106206289751220">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」和另外 <xliff:g id="NUMBER_OF_APPS">%2$s</xliff:g> 個應用程式在過去幾個月未有使用。輕按即可查看。"</string>
<string name="auto_revoke_before_notification_title_one" msgid="6758024954464359876">"1 個應用程式未有使用"</string>
<string name="auto_revoke_before_notification_title_many" msgid="4415543943846385685">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> 個應用程式未有使用"</string>
- <string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"為保護您的私隱,系統將會移除權限。輕按即可查看。"</string>
+ <string name="auto_revoke_before_notification_content_one" msgid="1156635373417068822">"為保護你的私隱,系統將會移除權限。輕按即可查看。"</string>
<string name="unused_apps_title" msgid="8589298917717872239">"不使用的應用程式"</string>
<string name="unused_apps_subtitle_after" msgid="2034267519506357898">"已移除以下應用程式的權限"</string>
<string name="unused_apps_subtitle_before" msgid="5233302577076132427">"系統將會移除以下應用程式的權限"</string>
<string name="unused_permissions_subtitle_two" msgid="2207266295008423015">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g>和<xliff:g id="PERM_NAME_1">%2$s</xliff:g>"</string>
<string name="unused_permissions_subtitle_many" msgid="4387289202207450238">"<xliff:g id="PERM_NAME_0">%1$s</xliff:g>、<xliff:g id="PERM_NAME_1">%2$s</xliff:g> 和另外 <xliff:g id="NUMBER_OF_PERMISSIONS">%3$s</xliff:g> 個權限"</string>
- <string name="unused_app_permissions_removed_summary" msgid="6779039455326071033">"為保護您的資料,系統已移除您在過去幾個月未使用應用程式的權限"</string>
- <string name="unused_app_permissions_removed_summary_some" msgid="5080490037831563441">"為保護您的資料,系統已移除您在過去幾個月沒有用過的部分應用程式的權限。"</string>
+ <string name="unused_app_permissions_removed_summary" msgid="6779039455326071033">"為保護你的資料,系統已移除你在過去幾個月未使用應用程式的權限"</string>
+ <string name="unused_app_permissions_removed_summary_some" msgid="5080490037831563441">"為保護你的資料,系統已移除你在過去幾個月沒有用過的部分應用程式的權限。"</string>
<string name="one_unused_app_summary" msgid="7831913934488881991">"1 個應用程式在過去幾個月未曾使用"</string>
<string name="num_unused_apps_summary" msgid="1870719749940571227">"<xliff:g id="NUMBER_OF_APPS">%s</xliff:g> 個應用程式在過去幾個月未曾使用"</string>
<string name="permission_subtitle_only_in_foreground" msgid="9068389431267377564">"只在使用應用程式時"</string>
@@ -343,63 +343,63 @@
<string name="no_apps_denied" msgid="7663435886986784743">"沒有拒絕任何應用程式"</string>
<string name="car_permission_selected" msgid="180837028920791596">"已選取"</string>
<string name="settings" msgid="5409109923158713323">"設定"</string>
- <string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"<xliff:g id="SERVICE_NAME">%s</xliff:g>可以取得您裝置的完整存取權"</string>
- <string name="accessibility_service_dialog_title_multiple" msgid="5527879210683548175">"<xliff:g id="NUM_SERVICES">%s</xliff:g> 個無障礙應用程式可以取得您裝置的完整存取權"</string>
- <string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」可以查看您的螢幕、操作和輸入內容、執行操作以及控制顯示屏。"</string>
- <string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"這些應用程式可以查看您的螢幕、動作和輸入內容、執行動作以及控制顯示屏。"</string>
+ <string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"<xliff:g id="SERVICE_NAME">%s</xliff:g>可以取得你裝置的完整存取權"</string>
+ <string name="accessibility_service_dialog_title_multiple" msgid="5527879210683548175">"<xliff:g id="NUM_SERVICES">%s</xliff:g> 個無障礙應用程式可以取得你裝置的完整存取權"</string>
+ <string name="accessibility_service_dialog_bottom_text_single" msgid="1128666197822205958">"「<xliff:g id="SERVICE_NAME">%s</xliff:g>」可以查看你的螢幕、操作和輸入內容、執行操作以及控制顯示屏。"</string>
+ <string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"這些應用程式可以查看你的螢幕、動作和輸入內容、執行動作以及控制顯示屏。"</string>
<string name="role_assistant_label" msgid="4727586018198208128">"預設數碼助理應用程式"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"數碼助理應用程式"</string>
- <string name="role_assistant_description" msgid="6622458130459922952">"小幫手應用程式能根據您正在查看的螢幕資訊提供協助。部分應用程式可同時支援啟動器及語音輸入服務,以提供更全面的協助。"</string>
+ <string name="role_assistant_description" msgid="6622458130459922952">"小幫手應用程式能根據你正在查看的螢幕資訊提供協助。部分應用程式可同時支援啟動器及語音輸入服務,以提供更全面的協助。"</string>
<string name="role_browser_label" msgid="2877796144554070207">"預設瀏覽器應用程式"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"瀏覽器應用程式"</string>
- <string name="role_browser_description" msgid="3465253637499842671">"此類應用程式可讓您存取互聯網,並會顯示您輕按的連結"</string>
+ <string name="role_browser_description" msgid="3465253637499842671">"此類應用程式可讓你存取互聯網,並會顯示你輕按的連結"</string>
<string name="role_browser_request_title" msgid="2895200507835937192">"要將 <xliff:g id="APP_NAME">%1$s</xliff:g> 設為預設瀏覽器應用程式嗎?"</string>
<string name="role_browser_request_description" msgid="5888803407905985941">"無需任何權限"</string>
<string name="role_dialer_label" msgid="1100224146343237968">"預設電話應用程式"</string>
<string name="role_dialer_short_label" msgid="7186888549465352489">"手機應用程式"</string>
- <string name="role_dialer_description" msgid="8768708633696539612">"此類應用程式允許您使用自己的裝置撥打和接聽電話"</string>
+ <string name="role_dialer_description" msgid="8768708633696539612">"此類應用程式允許你使用自己的裝置撥打和接聽電話"</string>
<string name="role_dialer_request_title" msgid="5959618560705912058">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設為預設手機應用程式嗎?"</string>
- <string name="role_dialer_request_description" msgid="6288839625724909320">"此應用程式將可存取您的相機、通訊錄、麥克風、電話及短訊"</string>
+ <string name="role_dialer_request_description" msgid="6288839625724909320">"此應用程式將可存取你的相機、通訊錄、麥克風、電話及短訊"</string>
<string name="role_dialer_search_keywords" msgid="3324448983559188087">"撥號器"</string>
<string name="role_sms_label" msgid="8456999857547686640">"預設短訊應用程式"</string>
<string name="role_sms_short_label" msgid="4371444488034692243">"短訊應用程式"</string>
- <string name="role_sms_description" msgid="3424020199148153513">"此類應用程式允許您使用自己手機號碼傳送和接收短訊、相片、影片和其他資料"</string>
+ <string name="role_sms_description" msgid="3424020199148153513">"此類應用程式允許你使用自己手機號碼傳送和接收短訊、相片、影片和其他資料"</string>
<string name="role_sms_request_title" msgid="7953552109601185602">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設為預設短訊應用程式嗎?"</string>
- <string name="role_sms_request_description" msgid="2691004766132144886">"此應用程式將可存取您的相機、通訊錄、檔案和媒體、麥克風、電話及短訊"</string>
+ <string name="role_sms_request_description" msgid="2691004766132144886">"此應用程式將可存取你的相機、通訊錄、檔案和媒體、麥克風、電話及短訊"</string>
<string name="role_sms_search_keywords" msgid="8022048144395047352">"短訊, 發短訊, 訊息, 傳送短訊"</string>
<string name="role_emergency_label" msgid="7028825857206842366">"預設緊急應用程式"</string>
<string name="role_emergency_short_label" msgid="2388431453335350348">"緊急應用程式"</string>
- <string name="role_emergency_description" msgid="5051840234887686630">"此類應用程式可讓您記錄及供救援人員存取醫療資訊、獲取惡劣天氣事件和災難事件警示,以及在需要幫助時通知他人"</string>
+ <string name="role_emergency_description" msgid="5051840234887686630">"此類應用程式可讓你記錄及供救援人員存取醫療資訊、獲取惡劣天氣事件和災難事件警示,以及在需要幫助時通知他人"</string>
<string name="role_emergency_request_title" msgid="8469579020654348567">"要將 <xliff:g id="APP_NAME">%1$s</xliff:g> 設為預設緊急應用程式嗎?"</string>
<string name="role_emergency_request_description" msgid="131645948770262850">"無需任何權限"</string>
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"ICE"</string>
<string name="role_home_label" msgid="3871847846649769412">"預設主畫面應用程式"</string>
<string name="role_home_short_label" msgid="8544733747952272337">"主畫面應用程式"</string>
- <string name="role_home_description" msgid="7997371519626556675">"這類應用程式通常稱為啟動器,可以取代 Android 裝置的主畫面,讓您存取裝置的內容和功能"</string>
+ <string name="role_home_description" msgid="7997371519626556675">"這類應用程式通常稱為啟動器,可以取代 Android 裝置的主畫面,讓你存取裝置的內容和功能"</string>
<string name="role_home_request_title" msgid="738136983453341081">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設為預設主畫面應用程式嗎?"</string>
<string name="role_home_request_description" msgid="2658833966716057673">"無需任何權限"</string>
<string name="role_home_search_keywords" msgid="3830755001192666285">"啟動器"</string>
<string name="role_call_redirection_label" msgid="5785304207206147590">"預設通話重新導向應用程式"</string>
<string name="role_call_redirection_short_label" msgid="7568143419571217757">"通話重新導向應用程式"</string>
- <string name="role_call_redirection_description" msgid="6091669882014664420">"此類應用程式允許您將撥出電話轉駁至其他手機號碼"</string>
+ <string name="role_call_redirection_description" msgid="6091669882014664420">"此類應用程式允許你將撥出電話轉駁至其他手機號碼"</string>
<string name="role_call_redirection_request_title" msgid="2816244455003562925">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設為預設通話重新導向應用程式嗎?"</string>
<string name="role_call_redirection_request_description" msgid="3118895714178527164">"無需任何權限"</string>
<string name="role_call_screening_label" msgid="883935222060878724">"預設來電顯示與騷擾電話應用程式"</string>
<string name="role_call_screening_short_label" msgid="2048465565063130834">"來電顯示與垃圾郵件應用程式"</string>
- <string name="role_call_screening_description" msgid="2349431420497468981">"此類應用程式讓您識別來電,並封鎖垃圾電話、錄音電話或騷擾電話號碼"</string>
+ <string name="role_call_screening_description" msgid="2349431420497468981">"此類應用程式讓你識別來電,並封鎖垃圾電話、錄音電話或騷擾電話號碼"</string>
<string name="role_call_screening_request_title" msgid="7358309224566977290">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設為預設來電顯示與垃圾郵件應用程式嗎?"</string>
<string name="role_call_screening_request_description" msgid="7338511921032446006">"無需任何權限"</string>
<string name="role_automotive_navigation_label" msgid="2701890757955474751">"預設導航應用程式"</string>
<string name="role_automotive_navigation_short_label" msgid="5165823092506922457">"導航應用程式"</string>
- <string name="role_automotive_navigation_description" msgid="7834601873792870134">"可提供名勝地點搜尋和行車路線導航指引的應用程式"</string>
+ <string name="role_automotive_navigation_description" msgid="7834601873792870134">"可提供興趣點搜尋和行車路線導航指引的應用程式"</string>
<string name="role_automotive_navigation_request_title" msgid="7525693151489384300">"要將「<xliff:g id="APP_NAME">%1$s</xliff:g>」設定為預設導航應用程式嗎?"</string>
<string name="role_automotive_navigation_request_description" msgid="7073023813249245540">"無需任何權限"</string>
- <string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> 將可與您的通知互動,並可存取電話、短訊、聯絡人和日曆。"</string>
+ <string name="role_watch_description" msgid="267003778693177779">"<xliff:g id="APP_NAME">%1$s</xliff:g> 將可與你的通知互動,並可存取電話、短訊、聯絡人和日曆。"</string>
<string name="role_app_streaming_description" msgid="7341638576226183992">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」將可存取通知,並可在已連結的裝置上串流播放應用程式。"</string>
- <string name="role_companion_device_computer_description" msgid="416099879217066377">"此服務會將您手機中的相片、媒體和通知與其他裝置共用。"</string>
+ <string name="role_companion_device_computer_description" msgid="416099879217066377">"此服務會將你手機中的相片、媒體和通知與其他裝置共用。"</string>
<string name="role_notes_label" msgid="7451627001058089536">"預設筆記應用程式"</string>
<string name="role_notes_short_label" msgid="8796604147546125285">"筆記應用程式"</string>
- <string name="role_notes_description" msgid="8496852798616883551">"讓您可以在裝置上寫筆記的應用程式"</string>
+ <string name="role_notes_description" msgid="8496852798616883551">"讓你可以在裝置上寫筆記的應用程式"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"筆記"</string>
<string name="request_role_current_default" msgid="738722892438247184">"目前預設"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"不要再詢問"</string>
@@ -436,14 +436,14 @@
<string name="no_special_app_access" msgid="6950277571805106247">"沒有特別應用程式權限"</string>
<string name="special_app_access_no_apps" msgid="4102911722787886970">"沒有應用程式"</string>
<string name="home_missing_work_profile_support" msgid="1756855847669387977">"不支援工作設定檔"</string>
- <string name="encryption_unaware_confirmation_message" msgid="8274491794636402484">"請注意:如果您重新啟動裝置並設定了螢幕鎖定,就必須先將裝置解鎖,才可執行這個應用程式。"</string>
+ <string name="encryption_unaware_confirmation_message" msgid="8274491794636402484">"請注意:如果你重新啟動裝置並設定了螢幕鎖定,就必須先將裝置解鎖,才可執行這個應用程式。"</string>
<string name="assistant_confirmation_message" msgid="7476540402884416212">"這個小幫手將能讀取系統目前使用的應用程式資料,包括螢幕顯示的資料或可在應用程式中存取的資料。"</string>
<string name="incident_report_channel_name" msgid="3144954065936288440">"分享偵錯資料"</string>
<string name="incident_report_notification_title" msgid="4635984625656519773">"要分享詳細的偵錯資料嗎?"</string>
<string name="incident_report_notification_text" msgid="3376480583513587923">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」要求上載偵錯資料。"</string>
<string name="incident_report_dialog_title" msgid="669104389325204095">"分享偵錯資料?"</string>
<string name="incident_report_dialog_intro" msgid="5897733669850951832">"系統偵測到問題。"</string>
- <string name="incident_report_dialog_text" msgid="5675553296891757523">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」要求上載此裝置於 <xliff:g id="DATE">%2$s</xliff:g><xliff:g id="TIME">%3$s</xliff:g>傳送的錯誤報告。錯誤報告包括您的裝置或應用程式記錄的個人資料,例如使用者名稱、位置資料、裝置識別碼和網絡資訊。只與您信任可存取這些資料的使用者和應用程式分享錯誤報告。要允許「<xliff:g id="APP_NAME_1">%4$s</xliff:g>」上載錯誤報告嗎?"</string>
+ <string name="incident_report_dialog_text" msgid="5675553296891757523">"「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」要求上載此裝置於 <xliff:g id="DATE">%2$s</xliff:g><xliff:g id="TIME">%3$s</xliff:g>傳送的錯誤報告。錯誤報告包括你的裝置或應用程式記錄的個人資料,例如使用者名稱、位置資料、裝置識別碼和網絡資訊。只與你信任可存取這些資料的使用者和應用程式分享錯誤報告。要允許「<xliff:g id="APP_NAME_1">%4$s</xliff:g>」上載錯誤報告嗎?"</string>
<string name="incident_report_error_dialog_text" msgid="4189647113387092272">"系統處理「<xliff:g id="APP_NAME">%1$s</xliff:g>」的錯誤報告時發生錯誤,因此已拒絕分享詳細的偵錯資料。很抱歉發生中斷情況。"</string>
<string name="incident_report_dialog_allow_label" msgid="2970242967721155239">"允許"</string>
<string name="incident_report_dialog_deny_label" msgid="3535314290677579383">"拒絕"</string>
@@ -454,52 +454,106 @@
<string name="adjust_user_sensitive_per_app_header" msgid="4543506440989005648">"突顯以下應用程式的使用情況"</string>
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"顯示「Google 助理」觸發偵測"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"使用麥克風啟用語音助手時,在狀態列中顯示圖示"</string>
- <string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您裝置上的相片和媒體嗎?"</string>
- <string name="permgrouprequest_contacts" msgid="8391550064551053695">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您的聯絡人嗎?"</string>
+ <string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你裝置上的相片和媒體嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
+ <string name="permgrouprequest_contacts" msgid="8391550064551053695">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的聯絡人嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取此裝置的位置資訊嗎?"</string>
- <string name="permgrouprequestdetail_location" msgid="2635935335778429894">"此應用程式目前只有您在使用時才能存取位置資訊"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
+ <string name="permgrouprequestdetail_location" msgid="2635935335778429894">"此應用程式目前只有你在使用時才能存取位置資訊"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取此裝置的位置資訊嗎?"</string>
- <string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"此應用程式可能想一直存取您的位置 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"此應用程式可能想一直存取你的位置 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」的位置存取權嗎?"</string>
- <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"此應用程式想一直存取您的位置 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"此應用程式想一直存取你的位置 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"要允許&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;尋找、連接及判斷附近裝置的相對位置嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 尋找、連接及判斷附近裝置的相對位置嗎?"<annotation id="link">"請在設定中授予權限。"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"要將<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>存取的位置資訊從概略位置改為精確位置嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取此裝置的概略位置資訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"精確位置"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"概略位置"</string>
- <string name="permgrouprequest_calendar" msgid="1493150855673603806">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您的日曆嗎?"</string>
+ <string name="permgrouprequest_calendar" msgid="1493150855673603806">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的日曆嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;傳送和查看短訊嗎?"</string>
- <string name="permgrouprequest_storage" msgid="8717773092518621602">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您裝置上的相片、媒體和檔案嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
+ <string name="permgrouprequest_storage" msgid="8717773092518621602">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你裝置上的相片、媒體和檔案嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 存取此裝置上的&lt;b&gt;相片、影片、音樂和音訊&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 存取此裝置上的&lt;b&gt;相片、影片、音樂、音訊和其他檔案&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 存取此裝置上的音樂和音訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"要允許 &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; 存取此裝置上的相片和影片嗎?"</string>
- <string name="permgrouprequest_more_photos" msgid="128933814654231321">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取此裝置上的相片和影片嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
+ <string name="permgrouprequest_more_photos" msgid="128933814654231321">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取此裝置上更多的相片和影片?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;錄音嗎?"</string>
- <string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"此應用程式將只能在您使用期間錄音"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
+ <string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"此應用程式將只能在你使用期間錄音"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;錄音嗎?"</string>
- <string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"此應用程式可能會要求隨時錄音 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"此應用程式可能會要求隨時錄音 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;?的麥克風存取權嗎?"</string>
- <string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"此應用程式想隨時錄音 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
- <string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您的體能活動嗎?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"此應用程式想隨時錄音 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的體能活動嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;拍照和錄製影片嗎?"</string>
- <string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"此應用程式將只能在您使用期間拍照及錄影"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
+ <string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"此應用程式將只能在你使用期間拍照及錄影"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;拍照和錄製影片嗎?"</string>
- <string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"此應用程式可能會要求隨時拍照及錄影 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"此應用程式可能會要求隨時拍照及錄影 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;?的相機存取權嗎?"</string>
- <string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"此應用程式想隨時拍照及錄影 (包括您沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
- <string name="permgrouprequest_calllog" msgid="2065327180175371397">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取您的手機通話記錄嗎?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
+ <string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"此應用程式想隨時拍照及錄影 (包括你沒有使用此應用程式時)。"<annotation id="link">"在設定中允許存取。"</annotation></string>
+ <string name="permgrouprequest_calllog" msgid="2065327180175371397">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的手機通話記錄嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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="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="7726767635834043501">"如要讓此應用程式隨時存取人體感應器資料 (即使在您沒有使用此應用程式時),請"<annotation id="link">"前往設定"</annotation>"。"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
+ <string name="permgrouprequest_sensors" msgid="4397358316850652235">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取與你身體機能相關的感應器資料嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
+ <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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
+ <string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"如要讓此應用程式隨時存取人體感應器資料 (即使在你沒有使用此應用程式時),請"<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
+ <string name="permgrouprequest_notifications" msgid="6396739062335106181">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;傳送通知給你嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"由管理員控制的權限"</string>
- <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」具有位置存取權"</string>
- <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"貴機構允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取你的位置資訊"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」有位置存取權"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"你的機構允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取位置資訊"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"其他權限"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"系統使用的權限"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"僅系統應用程式使用的權限。"</string>
@@ -512,15 +566,15 @@
<string name="privdash_label_none" msgid="5991866260360484858">"無"</string>
<string name="privdash_label_24h" msgid="1512532123865375319">"過去\n24 小時"</string>
<string name="privdash_label_7d" msgid="5645301995348656931">"過去\n7 天內"</string>
- <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> 受 Android 保護。系統會在此裝置上處理您的資料,因此狀態列或私隱資訊主頁不會顯示此應用程式的權限使用情況。"</string>
- <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> 受 Android 保護。系統會在此裝置上處理您的資料,因此私隱資訊主頁不會顯示此應用程式的權限使用情況。"</string>
+ <string name="exempt_mic_camera_info_label" msgid="6273581737010902815">"<xliff:g id="APP_NAME">%1$s</xliff:g> 受 Android 保護。系統會在此裝置上處理你的資料,因此狀態列或私隱資訊主頁不會顯示此應用程式的權限使用情況。"</string>
+ <string name="exempt_info_label" msgid="6286190981253476699">"<xliff:g id="APP_NAME">%1$s</xliff:g> 受 Android 保護。系統會在此裝置上處理你的資料,因此私隱資訊主頁不會顯示此應用程式的權限使用情況。"</string>
<string name="blocked_camera_title" msgid="1128510551791284384">"已封鎖裝置相機"</string>
<string name="blocked_microphone_title" msgid="1631517143648232585">"已封鎖裝置麥克風"</string>
<string name="blocked_location_title" msgid="2005608279812892383">"已關閉裝置位置"</string>
<string name="blocked_sensor_summary" msgid="4443707628305027375">"應用程式和服務"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"撥打緊急電話號碼時,系統仍可能會分享麥克風資料。"</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"變更"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"安全性和私隱權"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"保安和私隱"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"掃瞄裝置"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"關閉"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"要關閉此警示嗎?"</string>
@@ -531,9 +585,9 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"安全性和私隱狀態。<xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>。<xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"安全性設定"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"權限"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"安全性和私隱權"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"保安和私隱"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"檢查狀態"</string>
- <string name="privacy_controls_qs" msgid="5780144882040591169">"您的私隱權設定"</string>
+ <string name="privacy_controls_qs" msgid="5780144882040591169">"你的私隱權設定"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"更多設定"</string>
<string name="camera_toggle_label_qs" msgid="3880261453066157285">"相機存取權"</string>
<string name="microphone_toggle_label_qs" msgid="8132912469813396552">"麥克風存取權"</string>
@@ -571,30 +625,31 @@
<string name="media_confirm_dialog_message_q_to_s_visual_allow" msgid="3504335060843147760">"此應用程式不支援 Android 最新版本。如果此應用程式可存取相片和影片,也就能存取音樂和音訊檔案。"</string>
<string name="media_confirm_dialog_message_q_to_s_visual_deny" msgid="2145973462806481992">"此應用程式不支援 Android 最新版本。如果此應用程式無法存取音樂和音訊檔案,也就無法存取相片和影片。"</string>
<string name="safety_center_background_location_access_notification_title" msgid="8933610618810588237">"查看擁有背景位置資訊存取權的應用程式"</string>
- <string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"「<xliff:g id="APP_NAME">%s</xliff:g>」可隨時存取您的位置,即使應用程式關閉時亦然"</string>
+ <string name="safety_center_background_location_access_reminder_notification_content" msgid="4066560182507301022">"「<xliff:g id="APP_NAME">%s</xliff:g>」可隨時存取你的位置,即使應用程式關閉時亦然"</string>
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"查看擁有背景位置資訊存取權的應用程式"</string>
- <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"此應用程式可隨時存取您的位置,即使應用程式關閉時亦然。\n\n部分安全和緊急應用程式需要在背景存取您的位置,才能正常運作。"</string>
+ <string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"此應用程式可隨時存取你的位置,即使應用程式關閉時亦然。\n\n部分安全和緊急應用程式需要在背景存取你的位置,才能正常運作。"</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"已變更存取權"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"查看最近的位置資訊使用情況"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"私隱權設定"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"相機存取權"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"麥克風存取權"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"應用程式和服務"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"應用程式和服務。如果關閉此設定,系統仍會在您撥打緊急電話號碼時提供麥克風的資料。"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"應用程式和服務。如果關閉此設定,系統仍會在你撥打緊急電話號碼時提供麥克風的資料。"</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"查看有權存取位置的應用程式和服務"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"顯示剪貼簿存取通知"</string>
- <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"系統會在應用程式存取您複製的文字、圖片或其他內容時顯示訊息"</string>
+ <string name="show_clip_access_notification_summary" msgid="3532020182782112687">"系統會在應用程式存取你複製的文字、圖片或其他內容時顯示訊息"</string>
<string name="show_password_title" msgid="2877269286984684659">"顯示密碼"</string>
<string name="show_password_summary" msgid="1110166488865981610">"輸入時短暫顯示字元"</string>
<string name="permission_rationale_message_location" msgid="2153841534298068414">"此應用程式表明可能會與第三方分享位置資料"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"資料分享和位置"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"資料分享詳情的來源"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"開發人員向此裝置的製造商提供資料,說明此應用程式的資料分享方式,並可能會隨時間更新。"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"開發人員向"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>"提供資料,說明此應用程式的資料分享方式,並可能會隨時間更新。"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"應用程式可能分享位置資料作以下用途:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"資料分享方式因情況而異"</string>
<string name="permission_rationale_data_sharing_varies_message" msgid="4224469559084489222">"資料處理方法可因應用程式版本、使用情況、所在地區和年齡而異。"<annotation id="link">"進一步瞭解資料分享"</annotation></string>
<string name="permission_rationale_data_sharing_varies_message_without_link" msgid="4912763761399025094">"資料處理方法可因應用程式版本、使用情況、所在地區和年齡而異。"</string>
- <string name="permission_rationale_location_settings_title" msgid="7204145004850190953">"您的位置資料"</string>
+ <string name="permission_rationale_location_settings_title" msgid="7204145004850190953">"你的位置資料"</string>
<string name="permission_rationale_permission_settings_message" msgid="631286040979660267">"如要變更此應用程式的存取權,請前往"<annotation id="link">"私隱權設定"</annotation></string>
<string name="permission_rationale_purpose_app_functionality" msgid="8397736681065841405">"應用程式功能"</string>
<string name="permission_rationale_purpose_analytics" msgid="2070800501189620712">"數據分析"</string>
@@ -605,16 +660,14 @@
<string name="permission_rationale_purpose_account_management" msgid="2985772421946688879">"帳戶管理"</string>
<string name="app_permission_rationale_message" msgid="8511466916077100713">"資料安全"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"系統可能會分享位置資料"</string>
- <string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"此應用程式表明可能會與第三方分享您的位置資料"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"無法開啟此連結"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
+ <string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"此應用程式表明可能會與第三方分享你的位置資料"</string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"位置資料分享更新"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"查看已變更位置資料分享方式的應用程式"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"這些應用程式已變更位置資料分享方式。它們可能未曾分享位置資料,或現在可能分享這些資料作廣告或市場推廣用途。"</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"這些應用程式的開發人員向應用程式商店提供資料分享做法相關資料,並可能會隨時間更新這些資料。\n\n資料分享方法可因應用程式版本、使用情況、所在地區和年齡而異。"</string>
<string name="learn_about_data_sharing" msgid="4200480587079488045">"進一步瞭解資料分享"</string>
- <string name="shares_location_with_third_parties" msgid="2278051743742057767">"您的位置資料現已與第三方分享"</string>
- <string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"您的位置資料現已與第三方分享,以作廣告或市場推廣用途"</string>
+ <string name="shares_location_with_third_parties" msgid="2278051743742057767">"你的位置資料現已與第三方分享"</string>
+ <string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"你的位置資料現已與第三方分享,以作廣告或市場推廣用途"</string>
<string name="updated_in_last_days" msgid="8371811947153042322">"{count,plural, =0{於過去一天內更新}=1{於過去一天內更新}other{於過去 # 天內更新}}"</string>
<string name="no_updates_at_this_time" msgid="9031085635689982935">"目前沒有更新"</string>
<string name="safety_label_changes_notification_title" msgid="4479955083472203839">"資料分享更新"</string>
diff --git a/PermissionController/res/values-zh-rTW-v34/strings.xml b/PermissionController/res/values-zh-rTW-v34/strings.xml
index 2ac35c5d0..e473ca41b 100644
--- a/PermissionController/res/values-zh-rTW-v34/strings.xml
+++ b/PermissionController/res/values-zh-rTW-v34/strings.xml
@@ -22,6 +22,6 @@
<string name="health_connect_title" msgid="2132233890867430855">"Health Connect"</string>
<string name="health_connect_summary" msgid="815473513776882296">"管理應用程式的健康資料存取權"</string>
<string name="location_settings" msgid="8863940440881290182">"位置資訊存取權"</string>
- <string name="mic_toggle_description" msgid="1504101620086616040">"適用於應用程式和服務。如果關閉這項設定,系統仍會在你撥打緊急電話號碼時分享麥克風的資料"</string>
+ <string name="mic_toggle_description" msgid="1504101620086616040">"適用於應用程式和服務。即使關閉這項設定,系統仍可能會在你撥打緊急電話號碼時,分享麥克風資料"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"應用程式和服務"</string>
</resources>
diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml
index 90524a7cc..4c4e33791 100644
--- a/PermissionController/res/values-zh-rTW/strings.xml
+++ b/PermissionController/res/values-zh-rTW/strings.xml
@@ -83,7 +83,7 @@
<string name="default_permission_description" msgid="4624464917726285203">"執行不明的動作"</string>
<string name="app_permissions_group_summary" msgid="8788419008958284002">"已授權給 <xliff:g id="COUNT_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="COUNT_1">%2$d</xliff:g> 個)"</string>
<string name="app_permissions_group_summary2" msgid="4329922444840521150">"已授權給 <xliff:g id="COUNT_0">%1$d</xliff:g> 個應用程式 (共 <xliff:g id="COUNT_1">%2$d</xliff:g> 個)"</string>
- <string name="menu_show_system" msgid="4254021607027872504">"顯示系統程序"</string>
+ <string name="menu_show_system" msgid="4254021607027872504">"顯示系統設定"</string>
<string name="menu_hide_system" msgid="3855390843744028465">"隱藏系統程序"</string>
<string name="menu_show_7_days_data" msgid="8979611198508523706">"顯示過去 7 天內的使用情況"</string>
<string name="menu_show_24_hours_data" msgid="8228054833323380780">"顯示過去 24 小時內的使用情況"</string>
@@ -455,48 +455,102 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"顯示個人助理觸發偵測圖示"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"使用麥克風啟用語音小幫手時,在狀態列顯示相關圖示"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取裝置中的相片和媒體嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取你的聯絡人嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置的位置資訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"該應用程式只有在你使用時,才能存取位置資訊"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置的位置資訊嗎?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"這個應用程式可能會要求隨時存取你的位置資訊 (即使在你未使用此應用程式時)。"<annotation id="link">"如要授予權限,請前往「設定」"</annotation>"。"</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」的位置資訊存取權嗎?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"這個應用程式想要隨時存取你的位置資訊 (即使在你未使用此應用程式時)。"<annotation id="link">"如要授予權限,請前往「設定」"</annotation>"。"</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;尋找、連結及判斷附近裝置的相對位置嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;尋找、連結及判斷附近裝置的相對位置嗎?"<annotation id="link">"請前往「設定」授予權限。"</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"要將「<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>」可以存取的定位資訊從「概略位置」改為「精確位置」嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置的概略位置資訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"精確"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"概略"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取你的日曆嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」傳送及查看簡訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取裝置中的相片、媒體和檔案嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的&lt;b&gt;相片、影片、音樂和音訊&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的&lt;b&gt;相片、影片、音樂、音訊和其他檔案&lt;/b&gt;嗎?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的音樂和音訊嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的相片和影片嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取這部裝置上的其他相片和影片嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」錄音嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"這個應用程式只有在你使用時才能錄音"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」錄音嗎?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"這個應用程式要求取得隨時都能錄音的權限,即使你當下並未使用該應用程式。"<annotation id="link">"如要授予權限,請前往設定頁面。"</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」的麥克風存取權嗎?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"這個應用程式想取得隨時都能錄音的權限,即使你當下並未使用該應用程式。"<annotation id="link">"如要授予權限,請前往設定頁面。"</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的體能活動記錄嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」拍攝相片及錄製影片嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"這個應用程式只有在你使用時,才能拍照及錄影"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」拍照及錄影嗎?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"這個應用程式要求取得隨時都能拍照及錄影的權限,即使你當下並未使用該應用程式。"<annotation id="link">"如要授予權限,請前往設定頁面。"</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"要變更「<xliff:g id="APP_NAME">%1$s</xliff:g>」的相機存取權嗎?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"這個應用程式想取得隨時都能拍照及錄影的權限,即使你當下並未使用該應用程式。"<annotation id="link">"如要授予權限,請前往設定頁面。"</annotation></string>
<string name="permgrouprequest_calllog" msgid="2065327180175371397">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;存取你的通話記錄嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<string name="permgrouprequest_phone" msgid="1829234136997316752">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」撥打電話及管理通話嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<string name="permgrouprequest_sensors" msgid="4397358316850652235">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取與你生命徵象相關的感應器資料嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"如要讓這個應用程式能隨時存取人體感應器資料 (即使你當下並未使用該應用程式),請"<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>
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
+ <skip />
<string name="permgrouprequest_notifications" msgid="6396739062335106181">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;傳送通知嗎?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
+ <skip />
<string name="auto_granted_permissions" msgid="6009452264824455892">"由管理員控管的權限"</string>
<string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」具有位置存取權"</string>
<string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"貴機構允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」存取你的位置資訊"</string>
@@ -520,7 +574,7 @@
<string name="blocked_sensor_summary" msgid="4443707628305027375">"應用程式和服務"</string>
<string name="blocked_mic_summary" msgid="8960466941528458347">"當你撥打緊急電話號碼時,系統仍會提供麥克風的資料。"</string>
<string name="blocked_sensor_button_label" msgid="6742092634984289658">"變更"</string>
- <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"安全性與隱私"</string>
+ <string name="safety_center_dashboard_page_title" msgid="2810774008694315854">"安全性與隱私權"</string>
<string name="safety_center_rescan_button" msgid="4517514567809409596">"掃描裝置"</string>
<string name="safety_center_issue_card_dismiss_button" msgid="5113965506144222402">"關閉"</string>
<string name="safety_center_issue_card_dismiss_confirmation_title" msgid="2734809473425036382">"要關閉這個警示嗎?"</string>
@@ -531,7 +585,7 @@
<string name="safety_status_preference_title_and_summary_content_description" msgid="3511373256505058464">"安全性與隱私權狀態。<xliff:g id="OVERALL_SAFETY_STATUS">%1$s</xliff:g>。<xliff:g id="SUMMARY_OF_DEVICE_STATUS">%2$s</xliff:g>"</string>
<string name="security_settings" msgid="3808106921175271317">"安全性設定"</string>
<string name="sensor_permissions_qs" msgid="1022267900031317472">"權限"</string>
- <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"安全性與隱私"</string>
+ <string name="safety_privacy_qs_tile_title" msgid="727301867710374052">"安全性與隱私權"</string>
<string name="safety_privacy_qs_tile_subtitle" msgid="3621544532041936749">"檢查狀態"</string>
<string name="privacy_controls_qs" msgid="5780144882040591169">"你的隱私權控制項"</string>
<string name="security_settings_button_label_qs" msgid="8280343822465962330">"更多設定"</string>
@@ -580,7 +634,7 @@
<string name="camera_toggle_title" msgid="1251201397431837666">"相機存取權"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"麥克風存取權"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"應用程式和服務"</string>
- <string name="mic_toggle_description" msgid="9163104307990677157">"應用程式和服務。如果關閉這項設定,系統仍會在你撥打緊急電話號碼時提供麥克風的資料。"</string>
+ <string name="mic_toggle_description" msgid="9163104307990677157">"適用於應用程式和服務。即使關閉這項設定,系統仍可能會在你撥打緊急電話號碼時,分享麥克風資料。"</string>
<string name="location_settings_subtitle" msgid="2328360561197430695">"查看對位置擁有存取權的應用程式與服務"</string>
<string name="show_clip_access_notification_title" msgid="5168467637351109096">"顯示剪貼簿存取通知"</string>
<string name="show_clip_access_notification_summary" msgid="3532020182782112687">"系統會在應用程式存取你複製的文字、圖片或其他內容時顯示通知訊息"</string>
@@ -589,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"這個應用程式表示可能會將位置資料分享給第三方"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"資料分享與位置"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"資料分享的相關資訊來源"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"開發人員已將這個應用程式的資料分享做法相關資訊,提供給這部裝置的製造商,且可能會隨著時間更新這項資訊。"</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"開發人員已將這個應用程式的資料分享做法資訊提供給 "<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>",並可能會隨著時間更新這項資訊。"</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"這個應用程式分享位置資料的可能目的如下:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"資料分享的差異"</string>
@@ -606,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"資料安全"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"可能會分享位置資料"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"這個應用程式表示可能會將位置資料分享給第三方"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"無法開啟這個連結"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"位置資料分享更新"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"查看哪些應用程式變更了分享位置資料的做法"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"以下應用程式變更了分享位置資料的做法。這些應用程式先前可能未曾分享位置資料,也可能是現在為了廣告或行銷目的而分享這些資料。"</string>
diff --git a/PermissionController/res/values-zu-v33/strings.xml b/PermissionController/res/values-zu-v33/strings.xml
index bfffa738a..2b1861644 100644
--- a/PermissionController/res/values-zu-v33/strings.xml
+++ b/PermissionController/res/values-zu-v33/strings.xml
@@ -30,8 +30,7 @@
<string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Ezinye izexwayiso"</string>
<string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Chitha izexwayiso"</string>
<string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Nweba futhi ubone esinye isexwayiso}one{Nweba futhi ubone ezinye izexwayiso ezingu-#}other{Nweba futhi ubone ezinye izexwayiso ezingu-#}}"</string>
- <!-- no translation found for safety_center_issue_card_prefix_content_description (1447445289637043544) -->
- <skip />
+ <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Isexwayiso. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string>
<string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Isenzo siqediwe"</string>
<string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Hlola amasethingi angangeza ukuvikeleka kudivayisi yakho"</string>
<string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Amasethingi asheshayo wokuvikeleka nobumfihlo"</string>
diff --git a/PermissionController/res/values-zu/strings.xml b/PermissionController/res/values-zu/strings.xml
index d0f30b575..7703dc236 100644
--- a/PermissionController/res/values-zu/strings.xml
+++ b/PermissionController/res/values-zu/strings.xml
@@ -218,7 +218,7 @@
<string name="auto_revoked_app_summary_one" msgid="7093213590301252970">"<xliff:g id="PERMISSION_NAME">%s</xliff:g> imvume isusiwe"</string>
<string name="auto_revoked_app_summary_two" msgid="1910545340763709389">"<xliff:g id="PERMISSION_NAME_0">%1$s</xliff:g> nezimvume ze-<xliff:g id="PERMISSION_NAME_1">%2$s</xliff:g> zisusiwe"</string>
<string name="auto_revoked_app_summary_many" msgid="5930976230827378798">"<xliff:g id="PERMISSION_NAME">%1$s</xliff:g> nezinye izimvume ezingu-<xliff:g id="NUMBER">%2$s</xliff:g> zisusiwe"</string>
- <string name="unused_apps_page_title" msgid="6986983535677572559">"Unused apps"</string>
+ <string name="unused_apps_page_title" msgid="6986983535677572559">"Ama-app angasetshenzisiwe"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"Uma i-app ingasetshenziswa izinyanga ezimbalwa:\n\n• Izimvume ziyasuswa ukuze kuvikelwe idatha yakho\n• Izaziso ziyamiswa ukonga ibhethri\n• Amafayela okwesikhashana ayasuswa ukukhulula isikhala\n\nUkuze uphinde uvumele izimvume nezaziso, vula i-app."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Uma i-app ingasetshenziswa inyanga:\n\n• Izimvume ziyasuswa ukuze kuvikelwe idatha yakho\n• Amafayela esikhashana ayasuswa ukuze kuvulwe isikhala\n\nUkuze uphinde uvumele izimvume, vula i-app."</string>
<string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Kugcine ukuvulwa ngaphezu kwenyanga e-# edlule}one{Kugcine ukuvulwa ngaphezu kwezinyanga ezingu-# ezedlule}other{Kugcine ukuvulwa ngaphezu kwezinyanga ezingu-# ezedlule}}"</string>
@@ -226,13 +226,13 @@
<string name="last_opened_summary_short" msgid="1646067226191176825">"Kugcine ukuvulwa ngo-<xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Uma uvumela ukuphathwa kwawo wonke amafayela, lolu hlelo lokusebenza lungafinyelela, lulungise, futhi lususe noma yimaphi amafayela akusitoreji esifanayo kule divayisi noma isitoreji samadivayisi axhunyiwe. Uhlelo lokusebenza lungafinyelela amafayela ngaphandle kokukubuza."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Uvumela lolu hlelo lokusebenza lufinyelele, lulungise futhi lususe amafayela kudivayisi, noma kunoma yiziphi izitoreji zamadivayisi axhunyiwe? Lolu hlelo lokusebenza lungafinyelela amafayela ngaphandle kokukubuza."</string>
- <string name="permission_description_summary_generic" msgid="5401399408814903391">"Izinhlelo zokusebenza ezinale mvume zingenza lokhu <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
+ <string name="permission_description_summary_generic" msgid="5401399408814903391">"Ama-app anale mvume angakwazi <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
<string name="permission_description_summary_activity_recognition" msgid="2652850576497070146">"Izinhlelo zokusebenza ezinale mvume zingafinyelela umsebenzi wakho, njengokuhamba, ukugibela ibhayisikili, ukushayela, ukubala izinyathelo, nokuningi"</string>
<string name="permission_description_summary_calendar" msgid="103329982944411010">"Izinhlelo zokusebenza ezinale mvume zingafinyelela kukhalenda yakho"</string>
<string name="permission_description_summary_call_log" msgid="7321437186317577624">"Izinhlelo zokusebenza ezinale mvume zingafunda ziphinde zibhale irekhodi lamakholi"</string>
<string name="permission_description_summary_camera" msgid="108004375101882069">"Izinhlelo zokusebenza ezinale mvume zingathatha izithombe ziphinde zirekhode ividiyo"</string>
<string name="permission_description_summary_contacts" msgid="2337798886460408996">"Izinhlelo zokusebenza ezinale mvume zingafinyelela koxhumana nabo"</string>
- <string name="permission_description_summary_location" msgid="2817531799933480694">"Izinhlelo zokusebenza ezinale mvume zingafinyelela kundawo yale divayisi"</string>
+ <string name="permission_description_summary_location" msgid="2817531799933480694">"Ama-app anale mvume angafinyelela kundawo yale divayisi"</string>
<string name="permission_description_summary_nearby_devices" msgid="8269183818275073741">"Ama-app anale mvume angathola, axhume, futhi anqume ukuma okuhlobene kwamadivayisi aseduze"</string>
<string name="permission_description_summary_microphone" msgid="630834800308329907">"Izinhlelo zokusebenza ezinale mvume zingarekhoda umsindo"</string>
<string name="permission_description_summary_phone" msgid="4515277217435233619">"Izinhlelo zokusebenza ezinale mvume zingenza ziphinde ziphathe amakholi efoni"</string>
@@ -337,7 +337,7 @@
<string name="app_perms_content_provider_7d_all_files" msgid="7962416229708835558">"Kufinyelelwe ezinsukwini ezi-7 ezedlule • Wonke Amafayela"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"Azikho izimvume ezivunyelwe"</string>
<string name="no_permissions_denied" msgid="8159923922804043282">"Azikho izimvume ezinqatshelwe"</string>
- <string name="no_apps_allowed" msgid="7718822655254468631">"Azikho izinhlelo zokusebenza ezivunyelwe"</string>
+ <string name="no_apps_allowed" msgid="7718822655254468631">"Ama-app avunyelwe"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"Azikho izinhlelo zokusebenza ezivunyelwe kuwo wonke amafayela"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Azikho izinhlelo zokusebenza ezivunyelwe imidiya kuphela"</string>
<string name="no_apps_denied" msgid="7663435886986784743">"Azikho izinhlelo zokusebenza ezinqatshelwe"</string>
@@ -455,53 +455,105 @@
<string name="assistant_record_audio_user_sensitive_title" msgid="5532123360322362378">"Bonisa ukutholwa okucushwe umsizi"</string>
<string name="assistant_record_audio_user_sensitive_summary" msgid="6482937591816401619">"Bonisa isithonjana kwibha yesaziso uma imakrofoni isetshenzisiwe ukusebenzisa umsizi wezwi"</string>
<string name="permgrouprequest_storage_isolated" msgid="4892154224026852295">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele izithombe kanye nemidiya kudivayisi yakho?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage_isolated (5934218468708513375) -->
+ <skip />
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ithole ukufinyelela koxhumana nabo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_contacts (2270563860206654757) -->
+ <skip />
<string name="permgrouprequest_location" msgid="6990232580121067883">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kundawo yale divayisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_location (6641436550953715107) -->
+ <skip />
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"Uhlelo lokusebenza luzoba nokufinyelela kuphela kundawo ngenkathi usebenzisa uhlelo lokusebenza"</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kundawo yale divayisi?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_location (7660465507029650527) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_location" msgid="8021219324989662957">"Lolu hlelo lokusebenza lungafuna ukufinyelela indawo yakho ngaso sonke isikhathi, ngisho noma ungasebenzisi uhlelo lokusebenza. "<annotation id="link">"Vumela kokuthi izilungiselelo"</annotation>"."</string>
<string name="permgroupupgraderequest_location" msgid="8328408946822691636">"Shintsha ukufinyelela kwendawo kwe-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_location (4528266408056426513) -->
+ <skip />
<string name="permgroupupgraderequestdetail_location" msgid="1550899076845189165">"Lolu hlelo lokusebenza lufuna ukufinyelela kundawo yakho ngaso sonke isikhathi, nanoma ungasebenzisi uhlelo lokusebenza. "<annotation id="link">"Vumela kokuthi izilungiselelo"</annotation>"."</string>
<string name="permgrouprequest_nearby_devices" msgid="2272829282660436700">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ithole, ixhume, futhi anqume ukuma okuhlobene kwamadivayisi aseduze?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_nearby_devices (7919687165848885665) -->
+ <skip />
<string name="permgroupupgraderequestdetail_nearby_devices" msgid="6877531270654738614">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ithole, ixhume, futhi anqume ukuma okuhlobene kwamadivayisi aseduze? "<annotation id="link">"Vumela kumasethingi."</annotation></string>
<string name="permgrouprequest_fineupgrade" msgid="2334242928821697672">"Shintsha ukufinyelela indawo kwe-<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g> kusuka kokulinganiselwayo kuya kokunembile?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_fineupgrade (3947134846432067176) -->
+ <skip />
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele indawo elinganiselwe yale divayisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_coarselocation (9001956706241104626) -->
+ <skip />
<string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"Kunembile"</string>
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Cishe"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kukhalenda yakho?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_calendar (3103987548035171850) -->
+ <skip />
<string name="permgrouprequest_sms" msgid="5672063688745420991">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ithumele iphinde ibuke imilayezo ye-SMS?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_sms (7212083972999874267) -->
+ <skip />
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kuzithombe, imidiya, namafayela akudivayisi yakho?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_storage (872629037299467086) -->
+ <skip />
<string name="permgrouprequest_storage_q_to_s" msgid="8213701872983685505">"Vumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukuba ifinyelele izithombe, amavidiyo, umculo, nokulalelwayo, kule divayisi?"</string>
<string name="permgrouprequest_storage_pre_q" msgid="168130651144569428">"Vumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukuba ifinyelele izithombe, amavidiyo, umculo, okulalelwayo, namanye amafayela kule divayisi?"</string>
<string name="permgrouprequest_read_media_aural" msgid="2593365397347577812">"Vumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukuba ifinyelele umculo nokulalelwayo kule divayisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_aural (3331524384339036668) -->
+ <skip />
<string name="permgrouprequest_read_media_visual" msgid="5548780620779729975">"Vumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukuba ifinyelele izithombe namavidiyo kule divayisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_read_media_visual (5492319750632751551) -->
+ <skip />
<string name="permgrouprequest_more_photos" msgid="128933814654231321">"Vumela &lt;i-<xliff:g id="APP_NAME">%1$s</xliff:g>&gt; ukuba ifinyelele izithombe namavidiyo kule divayisi?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_more_photos (8946782319103584021) -->
+ <skip />
<string name="permgrouprequest_microphone" msgid="2825208549114811299">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi irekhode umsindo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_microphone (1266843551173029370) -->
+ <skip />
<string name="permgrouprequestdetail_microphone" msgid="8510456971528228861">"Uhlelo lokusebenza luzokwazi ukurekhoda imisindo kuphela kuyilapho usebenzisa uhlelo lokusebenza"</string>
<string name="permgroupbackgroundrequest_microphone" msgid="8874462606796368183">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi irekhode umsindo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_microphone (4990337225146130185) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_microphone" msgid="553702902263681838">"Lolu hlelo lokusebenza lungafuna ukurekhoda imisindo ngaso sonke isikhathi, ngisho nalapho ungasebenzisi uhlelo lokusebenza. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
<string name="permgroupupgraderequest_microphone" msgid="1362781696161233341">"Shintsha ukufinyelela kwemakrofoni kwe-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_microphone (222471025997100107) -->
+ <skip />
<string name="permgroupupgraderequestdetail_microphone" msgid="2870497719571464239">"Lolu hlelo lokusebenza lufuna ukurekhoda imisindo ngaso sonke isikhathi, ngisho nalapho ungasebenzisi uhlelo lokusebenza. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
<string name="permgrouprequest_activityRecognition" msgid="5415121592794230330">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi ifinyelele kumsebenzi wakho womzimba?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_activityRecognition (3408326850847755759) -->
+ <skip />
<string name="permgrouprequest_camera" msgid="5123097035410002594">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthatha izithombe iphinde irekhode ividiyo?"</string>
+ <!-- no translation found for permgrouprequest_device_aware_camera (3525106924487608868) -->
+ <skip />
<string name="permgrouprequestdetail_camera" msgid="9085323239764667883">"Lolu hlelo lokusebenza luzokwazi ukuthatha izithombe futhi lirekhode ividiyo kuphela kuyilapho usebenzisa uhlelo lokusebenza"</string>
<string name="permgroupbackgroundrequest_camera" msgid="1274286575704213875">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthatha izithombe iphinde irekhode ividiyo?"</string>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_camera (6718286540040964849) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_camera" msgid="4458783509089859078">"Lolu hlelo lokusebenza lungafuna ukuthatha izithombe futhi lirekhode ividiyo ngaso sonke isikhathi, ngisho nalapho ungasebenzi uhlelo lokusebenza. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
<string name="permgroupupgraderequest_camera" msgid="640758449200241582">"Shintsha ukufinyelela kwekhamera kwe-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;?"</string>
+ <!-- no translation found for permgroupupgraderequest_device_aware_camera (4198765626608612156) -->
+ <skip />
<string name="permgroupupgraderequestdetail_camera" msgid="6642747548010962597">"Lolu hlelo lokusebenza lufuna ukuthatha izithombe futhi lirekhode ividiyo ngaso sonke isikhathi, ngisho nalapho ungasebenzi uhlelo lokusebenza. "<annotation id="link">"Vumela kumasethingi."</annotation></string>
<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>
+ <!-- no translation found for permgrouprequest_device_aware_calllog (735079772627778095) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_phone (4389610977195521813) -->
+ <skip />
<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>
+ <!-- no translation found for permgrouprequest_device_aware_sensors (1900598688488188225) -->
+ <skip />
<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>
+ <!-- no translation found for permgroupbackgroundrequest_device_aware_sensors (7691308331448239716) -->
+ <skip />
<string name="permgroupbackgroundrequestdetail_sensors" msgid="7726767635834043501">"Ukuze uvumele le app ukuba ifinyelele idatha yenzwa yomzimba ngaso sonke isikhathi, ngisho nalapho 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="auto_granted_permissions" msgid="6009452264824455892">"Izimvume ezilawuliwe"</string>
- <!-- no translation found for auto_granted_location_permission_notification_title (7570818224669050377) -->
+ <!-- no translation found for permgroupupgraderequest_device_aware_sensors (3310667992344623159) -->
<skip />
- <!-- no translation found for auto_granted_permission_notification_body (5040234389205471318) -->
+ <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>
+ <!-- no translation found for permgrouprequest_device_aware_notifications (7307588961166360244) -->
<skip />
+ <string name="auto_granted_permissions" msgid="6009452264824455892">"Izimvume ezilawuliwe"</string>
+ <string name="auto_granted_location_permission_notification_title" msgid="7570818224669050377">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> inokufinyelela kwendawo"</string>
+ <string name="auto_granted_permission_notification_body" msgid="5040234389205471318">"Inhlangano yakho ivumela i-<xliff:g id="APP_NAME">%1$s</xliff:g> ukufinyelela indawo yakho"</string>
<string name="other_permissions_label" msgid="8986184335503271992">"Ezinye izimvume"</string>
<string name="not_used_permissions_label" msgid="3939839426115141264">"Izimvume ezisetshenziswa yisistimu"</string>
<string name="not_used_permissions_description" msgid="7595514824169388718">"Izimvume ezisetshenziswa yizinhlelo zokusebenza zesistimu kuphela."</string>
@@ -591,6 +643,7 @@
<string name="permission_rationale_message_location" msgid="2153841534298068414">"Le-app ithi ingabelana ngedatha yendawo nezinkampani engahlangene ngqo"</string>
<string name="permission_rationale_location_title" msgid="2404797182678793506">"Ukwabelana ngedatha nendawo"</string>
<string name="permission_rationale_data_sharing_source_title" msgid="6874604543125814316">"Lapho ulwazi lokwabelana ngedatha luvela khona"</string>
+ <string name="permission_rationale_data_sharing_device_manufacturer_message" msgid="7569261218145653185">"Unjiniyela unikezele ngolwazi kumkhiqizi wale divayisi mayelana nokuthi le app yabelana kanjani ngedatha. Unjiniyela angase abuyekeze lolu lwazi ngokuhamba kwesikhathi."</string>
<string name="permission_rationale_data_sharing_source_message" msgid="8330794595417986883">"Unjiniyela unikeze ulwazi ku-"<annotation id="link"><annotation id="install_source" example="App Store">"%1$s"</annotation></annotation>" mayelana nokuthi le-app yabelana kanjani ngedatha. Unjiniyela angase abuyekeze lolu lwazi ngokuhamba kwesikhathi."</string>
<string name="permission_rationale_location_purpose_title" msgid="5115877143670012618">"Le app ingabelana ngedatha yendawo ye-:"</string>
<string name="permission_rationale_permission_data_sharing_varies_title" msgid="9103718980919908316">"Ukwabelana ngedatha kuyahlukahluka"</string>
@@ -608,8 +661,6 @@
<string name="app_permission_rationale_message" msgid="8511466916077100713">"Ukuphepha kwedatha"</string>
<string name="app_location_permission_rationale_title" msgid="925420340572401350">"Idatha yendawo ingase yabiwe"</string>
<string name="app_location_permission_rationale_subtitle" msgid="6986985722752868692">"Le-app ithe ingabelana ngedatha yendawo nezinkampani ezingahlangene ngqo"</string>
- <string name="permission_rationale_data_sharing_link_error_title" msgid="4496607694785370249">"Ayikwazi ukuvula lelinki"</string>
- <string name="permission_rationale_data_sharing_link_error_message" msgid="8118116480850030215"></string>
<string name="data_sharing_updates_title" msgid="7996933386875213859">"Izibuyekezo zokwabelana ngedatha zendawo"</string>
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Buyekeza ama-app aguqule indlela angabelana ngayo ngedatha yendawo yakho"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Lama-app ashintshe indlela angabelana ngayo ngedatha yendawo yakho. Kungenzeka abakaze babelane ngayo ngaphambili, noma manje sebengase babelane ngayo ngezinjongo zokukhangisa noma zokumaketha."</string>
diff --git a/PermissionController/res/values/bools.xml b/PermissionController/res/values/bools.xml
index e97761843..b5f33b081 100644
--- a/PermissionController/res/values/bools.xml
+++ b/PermissionController/res/values/bools.xml
@@ -19,4 +19,5 @@
<resources>
<bool name="is_at_least_t">false</bool>
<bool name="is_at_least_u">false</bool>
+ <bool name="is_at_least_v">false</bool>
</resources>
diff --git a/PermissionController/res/values/colors.xml b/PermissionController/res/values/colors.xml
index e54edb506..b1d285104 100644
--- a/PermissionController/res/values/colors.xml
+++ b/PermissionController/res/values/colors.xml
@@ -32,4 +32,7 @@
<!-- overviewBackground is not visible from mainline, so UX provided this alternative.
system_neutral2_200 is v31+ so use this placeholder provided by ux -->
<color name="permission_rationale_overview_background">#DADCE0</color>
+
+ <!-- Wear related colors -->
+ <color name="wear_material_gray_600">#FF80868B</color>
</resources>
diff --git a/PermissionController/res/values/overlayable.xml b/PermissionController/res/values/overlayable.xml
index 850b5df40..8f81e446b 100644
--- a/PermissionController/res/values/overlayable.xml
+++ b/PermissionController/res/values/overlayable.xml
@@ -37,12 +37,24 @@
<item type="style" name="PermissionGrantTitleMessage" />
<item type="style" name="PermissionGrantDetailMessage" />
+ <item type="style" name="PermissionGrantPermissionRationaleContent" />
+ <item type="style" name="PermissionGrantPermissionRationaleIcon" />
+ <item type="style" name="PermissionGrantPermissionRationaleMessage" />
+ <item type="style" name="PermissionGrantPermissionRationaleMoreInfoIcon" />
+
+ <item type="color" name="permission_rationale_overview_background" />
+
+ <item type="style" name="PermissionLocationAccuracyRadioGroupMaterial3" />
+ <item type="style" name="PermissionLocationAccuracyFineImageViewMaterial3" />
+ <item type="style" name="PermissionLocationAccuracyCoarseImageViewMaterial3" />
+
+ <item type="style" name="PermissionLocationAccuracyRadioFine" />
+ <item type="style" name="PermissionLocationAccuracyRadioCoarse" />
+
<item type="style" name="PermissionGrantButtonList" />
<item type="style" name="PermissionGrantButtonBarSpace" />
<item type="style" name="PermissionGrantButton" />
- <!-- IDs for V31 only -->
-
<item type="style" name="PermissionGrantButtonTop" />
<item type="style" name="PermissionGrantButtonMiddle" />
<item type="style" name="PermissionGrantButtonBottom" />
@@ -52,23 +64,27 @@
<item type="style" name="PermissionGrantButtonAllowMaterial3" />
<item type="style" name="PermissionGrantButtonAllowForegroundMaterial3" />
<item type="style" name="PermissionGrantButtonAllowOneTimeMaterial3" />
+ <item type="style" name="PermissionGrantButtonAllowSelectedMaterial3" />
+ <item type="style" name="PermissionGrantButtonAllowAllMaterial3" />
<item type="style" name="PermissionGrantButtonDenyMaterial3" />
<item type="style" name="PermissionGrantButtonNoUpgradeMaterial3" />
+ <item type="style" name="PermissionGrantButtonDontAllowMoreMaterial3" />
+
+ <!-- Used in V30 only -->
- <!-- END IDs for V31 only -->
+ <item type="style" name="PermissionLocationAccuracyFineImageView" />
+ <item type="style" name="PermissionLocationAccuracyCoarseImageView" />
<item type="style" name="PermissionGrantButtonAllow" />
<item type="style" name="PermissionGrantButtonAllowForeground" />
<item type="style" name="PermissionGrantButtonAllowOneTime" />
+ <item type="style" name="PermissionGrantButtonAllowSelected" />
+ <item type="style" name="PermissionGrantButtonAllowAll" />
<item type="style" name="PermissionGrantButtonDeny" />
<item type="style" name="PermissionGrantButtonNoUpgrade" />
+ <item type="style" name="PermissionGrantButtonDontAllowMore" />
- <item type="style" name="PermissionGrantPermissionRationaleContent" />
- <item type="style" name="PermissionGrantPermissionRationaleIcon" />
- <item type="style" name="PermissionGrantPermissionRationaleMessage" />
- <item type="style" name="PermissionGrantPermissionRationaleMoreInfoIcon" />
-
- <item type="color" name="permission_rationale_overview_background" />
+ <!-- END Used in V30 only -->
<!-- END PERMISSION GRANT DIALOG -->
@@ -526,4 +542,4 @@
</policy>
</overlayable>
-</resources> \ No newline at end of file
+</resources>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 08d1b6b2d..774578b6c 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1390,36 +1390,58 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group. Shows in the isolated storage case. 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="permgrouprequest_storage_isolated">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and media on your device?</string>
+ <!-- Message shown to the user when the apps requests permission from this group. Shows in the isolated storage case. 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="permgrouprequest_device_aware_storage_isolated">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and media on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_contacts">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your contacts?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_contacts">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your contacts on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_location">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_location">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device_name" example="tablet">%2$s</xliff:g>\u2019s&lt;/b> location?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the location 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_location">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location?</string>
+ <string name="permgroupbackgroundrequest_device_aware_location">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device_name" example="tablet">%2$s</xliff:g>\u2019s location?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_location">This app may want to access your location all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the location 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="permgroupupgraderequest_location">Change location access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
+ <!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background on a specific device. 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="permgroupupgraderequest_device_aware_location">Change location access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_location">This app wants to access your location all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_nearby_devices">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_nearby_devices">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to discovery and connect to nearby devices while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_nearby_devices">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices? <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the app requests permission to upgrade to fine location [CHAR LIMIT=120] -->
<string name="permgrouprequest_fineupgrade">Change <xliff:g id="app_name" example="Gmail">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\u2019s location access from approximate to precise?</string>
+ <!-- Message shown to the user when the app requests permission to upgrade to fine location on a specific device [CHAR LIMIT=120] -->
+ <string name="permgrouprequest_device_aware_fineupgrade">Change <xliff:g id="app_name" example="Gmail">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\u2019s location access on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b> from approximate to precise?</string>
<!-- Message shown to the user when the app requests permission to use coarse location [CHAR LIMIT=120] -->
<string name="permgrouprequest_coarselocation">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s approximate location?</string>
+ <!-- Message shown to the user when the app requests permission to use coarse location for a specific device [CHAR LIMIT=120] -->
+ <string name="permgrouprequest_device_aware_coarselocation">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>\u2019s approximate location?</string>
<!-- Text for the FINE location image [CHAR LIMIT=20] -->
<string name="permgrouprequest_finelocation_imagetext">Precise</string>
<!-- Text for the COARSE location image [CHAR LIMIT=20] -->
@@ -1429,14 +1451,26 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="permgrouprequest_calendar">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your calendar?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_calendar">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your calendar on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_sms">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send and view SMS messages?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_sms">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send and view SMS messages on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_storage">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos, media, and files on your device?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_storage">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos, media, and files on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_storage_q_to_s">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access &lt;b>photos, videos, music, and audio&lt;/b> on this device?</string>
@@ -1448,25 +1482,41 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_read_media_aural">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access music and audio on this device?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_read_media_aural">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access music and audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_read_media_visual">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and videos on this device?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_read_media_visual">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and videos on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_more_photos">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access more photos and videos on this device?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_more_photos">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access more photos and videos on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_microphone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_microphone">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_microphone">The app will only be able to record audio while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the microphone 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_microphone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
+ <string name="permgroupbackgroundrequest_device_aware_microphone">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_microphone">This app may want to record audio all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the microphone 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="permgroupupgraderequest_microphone">Change microphone access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
+ <!-- Message shown to the user when the apps requests permission to use the microphone 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="permgroupupgraderequest_device_aware_microphone">Change microphone access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_microphone">This app wants to record audio all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
@@ -1474,46 +1524,76 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="permgrouprequest_activityRecognition">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your physical activity?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_activityRecognition">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your physical activity on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_camera">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video?</string>
+
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_camera">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_camera">The app will only be able to take pictures and record video while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the camera 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_camera">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video?</string>
+ <!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background on a specific device. 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_device_aware_camera">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_camera">This app may want to take pictures and record video all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the camera 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="permgroupupgraderequest_camera">Change camera access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
+ <!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background on a specific device. 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="permgroupupgraderequest_device_aware_camera">Change camera access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_camera">This app wants to take pictures and record video all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_calllog">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your phone call logs?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_calllog">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your phone call logs on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_phone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_phone">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_sensors">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_sensors">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</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></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>
+ <!-- Message shown to the user when the apps requests permission to use the bosy sensors while app is in foreground and background on a specific device. 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_device_aware_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 on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</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="permgroupbackgroundrequestdetail_sensors">To let this app access body sensor data all the time, even when you\u2019re not using the app, <annotation id="link">go to settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the body 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="permgroupupgraderequest_sensors">Keep allowing &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access body sensor data while app is in use?</string>
+ <!-- Message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background on a specific device. 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="permgroupupgraderequest_device_aware_sensors">Keep allowing &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access body sensor data on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b> while app is in use?</string>
<!-- Message shown to the user when the apps requests permission from this group. 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="permgrouprequest_notifications">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send you notifications?</string>
+ <!-- Message shown to the user when the apps requests permission from this group on a specific device. 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="permgrouprequest_device_aware_notifications">Allow
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send you notifications on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
<!-- Notification shown to the user when location permissions are auto-granted by admin policy. These are for when the admin is forcing the permission and the user cannot control it. [CHAR LIMIT=120]-->
<string name="auto_granted_permissions">Controlled permissions</string>
diff --git a/PermissionController/res/values/styles.xml b/PermissionController/res/values/styles.xml
index 11b9ebec1..a03b71e9d 100644
--- a/PermissionController/res/values/styles.xml
+++ b/PermissionController/res/values/styles.xml
@@ -51,7 +51,7 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:orientation">vertical</item>
- <item name="android:paddingTop">18dp</item>
+ <item name="android:paddingTop">24dp</item>
<item name="android:paddingBottom">24dp</item>
<item name="android:paddingLeft">24dp</item>
<item name="android:paddingRight">24dp</item>
@@ -233,16 +233,16 @@
parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonAllowOneTime"
parent="@style/PermissionGrantButton"></style>
- <style name="PermissionGrantButtonAllowAll"
- parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonAllowSelected"
parent="@style/PermissionGrantButton"></style>
- <style name="PermissionGrantButtonDontAllowMore"
+ <style name="PermissionGrantButtonAllowAll"
parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonDeny"
parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonNoUpgrade"
parent="@style/PermissionGrantButton"></style>
+ <style name="PermissionGrantButtonDontAllowMore"
+ parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonAllowMaterial3"
parent="@style/PermissionGrantButton"></style>
@@ -256,10 +256,6 @@
parent="@style/PermissionGrantButton"></style>
<style name="PermissionGrantButtonAllowAllMaterial3"
parent="@style/PermissionGrantButton"></style>
- <style name="PermissionGrantButtonAllowSelectedPhotosMaterial3"
- parent="@style/PermissionGrantButton"></style>
- <style name="PermissionGrantButtonDontAllowMorePhotosMaterial3"
- parent="@style/PermissionGrantButton"></style>
<!-- END PERMISSION GRANT DIALOG -->
diff --git a/PermissionController/res/values/themes.xml b/PermissionController/res/values/themes.xml
index 76196a050..4f59ec29d 100644
--- a/PermissionController/res/values/themes.xml
+++ b/PermissionController/res/values/themes.xml
@@ -138,4 +138,6 @@
<item name="android:filterTouchesWhenObscured">true</item>
</style>
+ <style name="Theme.PermissionController.IncidentReportDialog"
+ parent="@style/Theme.DeviceDefault.Dialog.NoActionBar.DayNight" />
</resources>
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index 2f8f5a291..f48af8be7 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -78,6 +78,7 @@
<permission name="android.permission.READ_MEDIA_AUDIO" minSdkVersion="33" />
<permission name="android.permission.READ_MEDIA_VIDEO" minSdkVersion="33" />
<permission name="android.permission.READ_MEDIA_IMAGES" minSdkVersion="33" />
+ <permission name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" minSdkVersion="34" />
</permission-set>
<permission-set name="nearby_devices">
@@ -667,6 +668,7 @@
<permission name="android.permission.SET_TIME" minSdkVersion="34" />
<permission name="android.permission.SET_TIME_ZONE" minSdkVersion="34" />
<permission name="android.permission.SATELLITE_COMMUNICATION" minSdkVersion="34" />
+ <permission name="android.permission.ALWAYS_UPDATE_WALLPAPER" minSdkVersion="35" />
</permissions>
</role>
@@ -1101,7 +1103,6 @@
-->
<role
name="android.app.role.SYSTEM_UI"
- behavior="SystemUiRoleBehavior"
defaultHolders="config_systemUi"
exclusive="true"
minSdkVersion="31"
@@ -1610,4 +1611,29 @@
</service>
</required-components>
</role>
+
+ <role
+ name="android.app.role.RETAIL_DEMO"
+ behavior="RetailDemoRoleBehavior"
+ defaultHolders="config_defaultRetailDemo"
+ exclusive="true"
+ minSdkVersion="35"
+ static="true"
+ visible="false">
+ <permissions>
+ <permission name="android.permission.ACCESS_BLOBS_ACROSS_USERS" />
+ <permission name="android.permission.CHANGE_CONFIGURATION" />
+ <permission name="android.permission.MODIFY_DAY_NIGHT_MODE" />
+ <permission name="android.permission.MODIFY_PHONE_STATE" />
+ <permission name="android.permission.OBSERVE_APP_USAGE" />
+ <permission name="android.permission.QUERY_USERS" />
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+ <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" />
+ <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" />
+ <permission name="android.permission.WRITE_SETTINGS" />
+ </permissions>
+ <app-op-permissions>
+ <app-op-permission name="android.permission.PACKAGE_USAGE_STATS" />
+ </app-op-permissions>
+ </role>
</roles>
diff --git a/PermissionController/res/xml/safety_center_dashboard.xml b/PermissionController/res/xml/safety_center_dashboard.xml
index 216ef318e..e3951ca83 100644
--- a/PermissionController/res/xml/safety_center_dashboard.xml
+++ b/PermissionController/res/xml/safety_center_dashboard.xml
@@ -29,6 +29,11 @@
android:layout="@layout/preference_category_no_label"
app:selectable="false" />
+ <!-- TODO: b/291574390 - Move this to the issue drawer or status card view instead of having a
+ separate preference just for this margin/padding -->
+ <com.android.permissioncontroller.safetycenter.ui.EntriesTopPaddingPreference
+ android:key="entries_top_padding" />
+
<com.android.permissioncontroller.safetycenter.ui.ComparablePreferenceCategory
android:key="entries_group"
android:title="@string/safety_center_entries_category_title"
@@ -36,7 +41,7 @@
<com.android.permissioncontroller.safetycenter.ui.ComparablePreferenceCategory
android:key="static_entries_group"
- android:layout="@layout/spaced_preference_category_no_label"
+ android:layout="@layout/preference_category_no_label"
app:selectable="false" />
<com.android.permissioncontroller.safetycenter.ui.SpacerPreference
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
index 12710cfd3..eb1ceb3fa 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/AssistantRoleBehavior.java
@@ -20,6 +20,7 @@ import android.app.ActivityManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -54,10 +55,6 @@ public class AssistantRoleBehavior implements RoleBehavior {
private static final String LOG_TAG = AssistantRoleBehavior.class.getSimpleName();
- private static final Intent ASSIST_SERVICE_PROBE =
- new Intent(VoiceInteractionService.SERVICE_INTERFACE);
- private static final Intent ASSIST_ACTIVITY_PROBE = new Intent(Intent.ACTION_ASSIST);
-
@Override
public void onRoleAdded(@NonNull Role role, @NonNull Context context) {
PackageManager packageManager = context.getPackageManager();
@@ -82,81 +79,72 @@ public class AssistantRoleBehavior implements RoleBehavior {
@Override
public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
+ return getQualifyingPackagesInternal(null, user, context);
+ }
+
+ @Nullable
+ @Override
+ public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
+ @NonNull Context context) {
+ return !getQualifyingPackagesInternal(packageName, Process.myUserHandle(), context)
+ .isEmpty();
+ }
+
+ @NonNull
+ private List<String> getQualifyingPackagesInternal(@Nullable String filterPackageName,
+ @NonNull UserHandle user, @NonNull Context context) {
Context userContext = UserUtils.getUserContext(context, user);
ActivityManager userActivityManager = userContext.getSystemService(ActivityManager.class);
PackageManager userPackageManager = userContext.getPackageManager();
- Set<String> availableAssistants = new ArraySet<>();
+ Set<String> packageNames = new ArraySet<>();
if (!userActivityManager.isLowRamDevice()) {
- List<ResolveInfo> services = userPackageManager.queryIntentServices(
- ASSIST_SERVICE_PROBE, PackageManager.GET_META_DATA
+ Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
+ if (filterPackageName != null) {
+ serviceIntent.setPackage(filterPackageName);
+ }
+ List<ResolveInfo> serviceResolveInfos = userPackageManager.queryIntentServices(
+ serviceIntent, PackageManager.GET_META_DATA
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- int numServices = services.size();
- for (int i = 0; i < numServices; i++) {
- ResolveInfo service = services.get(i);
-
- if (isAssistantVoiceInteractionService(userPackageManager, service.serviceInfo)) {
- availableAssistants.add(service.serviceInfo.packageName);
+ int serviceResolveInfosSize = serviceResolveInfos.size();
+ for (int i = 0; i < serviceResolveInfosSize; i++) {
+ ResolveInfo serviceResolveInfo = serviceResolveInfos.get(i);
+
+ ServiceInfo serviceInfo = serviceResolveInfo.serviceInfo;
+ if (!isAssistantVoiceInteractionService(userPackageManager, serviceInfo)) {
+ if (filterPackageName != null) {
+ Log.w(LOG_TAG, "Package " + filterPackageName
+ + " has an unqualified voice interaction service");
+ }
+ continue;
}
+
+ packageNames.add(serviceInfo.packageName);
}
}
- List<ResolveInfo> activities = userPackageManager.queryIntentActivities(
- ASSIST_ACTIVITY_PROBE, PackageManager.MATCH_DEFAULT_ONLY
+ Intent activityIntent = new Intent(Intent.ACTION_ASSIST);
+ if (filterPackageName != null) {
+ activityIntent.setPackage(filterPackageName);
+ }
+ List<ResolveInfo> activityResolveInfos = userPackageManager.queryIntentActivities(
+ activityIntent, PackageManager.MATCH_DEFAULT_ONLY
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- int numActivities = activities.size();
- for (int i = 0; i < numActivities; i++) {
- availableAssistants.add(activities.get(i).activityInfo.packageName);
- }
-
- return new ArrayList<>(availableAssistants);
- }
+ int activityResolveInfosSize = activityResolveInfos.size();
+ for (int i = 0; i < activityResolveInfosSize; i++) {
+ ResolveInfo activityResolveInfo = activityResolveInfos.get(i);
- @Nullable
- @Override
- public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
- @NonNull Context context) {
- ActivityManager activityManager = context.getSystemService(ActivityManager.class);
- PackageManager packageManager = context.getPackageManager();
-
- boolean hasAssistantService = false;
- if (!activityManager.isLowRamDevice()) {
- Intent pkgServiceProbe = new Intent(ASSIST_SERVICE_PROBE).setPackage(packageName);
- List<ResolveInfo> services = packageManager.queryIntentServices(pkgServiceProbe,
- PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- hasAssistantService = !services.isEmpty();
- int numServices = services.size();
- for (int i = 0; i < numServices; i++) {
- ResolveInfo service = services.get(i);
-
- if (isAssistantVoiceInteractionService(packageManager, service.serviceInfo)) {
- return true;
- }
+ ActivityInfo activityInfo = activityResolveInfo.activityInfo;
+ if (!activityInfo.exported) {
+ continue;
}
- }
- Intent pkgActivityProbe = new Intent(ASSIST_ACTIVITY_PROBE).setPackage(packageName);
- boolean hasAssistantActivity = !packageManager.queryIntentActivities(pkgActivityProbe,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE).isEmpty();
- if (!hasAssistantActivity) {
- Log.w(LOG_TAG, "Package " + packageName + " not qualified for " + role.getName()
- + " due to " + (hasAssistantService ? "unqualified" : "missing")
- + " service and missing activity");
+ packageNames.add(activityInfo.packageName);
}
- return hasAssistantActivity;
- }
-
- @Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- }
-
- @Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
+ return new ArrayList<>(packageNames);
}
private boolean isAssistantVoiceInteractionService(@NonNull PackageManager pm,
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
index 3254bc6e4..61fb7dae5 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/HomeRoleBehavior.java
@@ -22,12 +22,16 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
+import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import com.android.modules.utils.build.SdkLevel;
+import com.android.role.controller.model.AppOpPermissions;
import com.android.role.controller.model.Permissions;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
@@ -51,6 +55,18 @@ public class HomeRoleBehavior implements RoleBehavior {
android.Manifest.permission.WRITE_CALL_LOG,
android.Manifest.permission.READ_CONTACTS);
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private static final List<String> WEAR_PERMISSIONS_T = Arrays.asList(
+ android.Manifest.permission.POST_NOTIFICATIONS,
+ android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY);
+
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ private static final List<String> WEAR_PERMISSIONS_V = Arrays.asList(
+ android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER);
+
+ private static final List<String> WEAR_APP_OP_PERMISSIONS = Arrays.asList(
+ android.Manifest.permission.SYSTEM_ALERT_WINDOW);
+
@Override
public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user,
@NonNull Context context) {
@@ -97,11 +113,12 @@ public class HomeRoleBehavior implements RoleBehavior {
public static boolean isSettingsApplication(@NonNull ApplicationInfo applicationInfo,
@NonNull Context context) {
PackageManager packageManager = context.getPackageManager();
- ResolveInfo resolveInfo = packageManager.resolveActivity(new Intent(
- Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+ ResolveInfo resolveInfo = packageManager.resolveActivity(
+ new Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
| PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- if (resolveInfo == null || resolveInfo.activityInfo == null) {
+ if (resolveInfo == null || resolveInfo.activityInfo == null
+ || !resolveInfo.activityInfo.exported) {
return false;
}
return Objects.equals(applicationInfo.packageName, resolveInfo.activityInfo.packageName);
@@ -131,6 +148,20 @@ public class HomeRoleBehavior implements RoleBehavior {
Arrays.asList(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES),
true, false, true, false, false, context);
}
+
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (SdkLevel.isAtLeastT()) {
+ Permissions.grant(packageName, WEAR_PERMISSIONS_T,
+ true, false, true, false, false, context);
+ for (String permission : WEAR_APP_OP_PERMISSIONS) {
+ AppOpPermissions.grant(packageName, permission, true, context);
+ }
+ }
+ if (SdkLevel.isAtLeastV()) {
+ Permissions.grant(packageName, WEAR_PERMISSIONS_V,
+ true, false, true, false, false, context);
+ }
+ }
}
@Override
@@ -145,6 +176,18 @@ public class HomeRoleBehavior implements RoleBehavior {
Arrays.asList(android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES),
true, false, false, context);
}
+
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ if (SdkLevel.isAtLeastT()) {
+ Permissions.revoke(packageName, WEAR_PERMISSIONS_T, true, false, false, context);
+ for (String permission : WEAR_APP_OP_PERMISSIONS) {
+ AppOpPermissions.revoke(packageName, permission, context);
+ }
+ }
+ if (SdkLevel.isAtLeastV()) {
+ Permissions.revoke(packageName, WEAR_PERMISSIONS_V, true, false, false, context);
+ }
+ }
}
/**
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java
new file mode 100644
index 000000000..831714843
--- /dev/null
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/RetailDemoRoleBehavior.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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.role.controller.behavior;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.role.controller.model.Role;
+import com.android.role.controller.model.RoleBehavior;
+
+import java.util.Arrays;
+
+/**
+ * Class for behavior of the Retail Demo role.
+ */
+@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+public class RetailDemoRoleBehavior implements RoleBehavior {
+
+ @Override
+ public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName,
+ @NonNull Context context) {
+ if (Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.DEVICE_DEMO_MODE, 0) == 0) {
+ return false;
+ }
+ DevicePolicyManager devicePolicyManager =
+ context.getSystemService(DevicePolicyManager.class);
+ if (!(devicePolicyManager.isDeviceOwnerApp(packageName)
+ || devicePolicyManager.isProfileOwnerApp(packageName))) {
+ return false;
+ }
+ // Fallback to do additional default check.
+ return null;
+ }
+
+ @Override
+ public boolean isAvailableAsUser(@NonNull Role role, @NonNull UserHandle user,
+ @NonNull Context context) {
+ UserManager userManager = context.getSystemService(UserManager.class);
+ return userManager.isSystemUser() || userManager.isMainUser() || userManager.isDemoUser();
+ }
+}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java
deleted file mode 100644
index 210c2313f..000000000
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/SystemUiRoleBehavior.java
+++ /dev/null
@@ -1,59 +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.role.controller.behavior;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-import androidx.annotation.NonNull;
-
-import com.android.modules.utils.build.SdkLevel;
-import com.android.role.controller.model.AppOpPermissions;
-import com.android.role.controller.model.Role;
-import com.android.role.controller.model.RoleBehavior;
-
-import java.util.Arrays;
-import java.util.List;
-
-/** The role behavior for system ui. */
-public class SystemUiRoleBehavior implements RoleBehavior {
-
- private static final List<String> WEAR_APP_OP_PERMISSIONS =
- Arrays.asList(android.Manifest.permission.SYSTEM_ALERT_WINDOW);
-
- @Override
- public void grant(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- if (SdkLevel.isAtLeastT()) {
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- for (String permission : WEAR_APP_OP_PERMISSIONS) {
- AppOpPermissions.grant(packageName, permission, true, context);
- }
- }
- }
- }
-
- @Override
- public void revoke(@NonNull Role role, @NonNull String packageName, @NonNull Context context) {
- if (SdkLevel.isAtLeastT()) {
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- for (String permission : WEAR_APP_OP_PERMISSIONS) {
- AppOpPermissions.revoke(packageName, permission, context);
- }
- }
- }
- }
-}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java b/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
index 0c4a14574..2d02d4204 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Permission.java
@@ -60,9 +60,9 @@ public class Permission {
* @return whether this permission is available
*/
public boolean isAvailable() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinSdkVersion;
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
index 58c878e56..25c97aefb 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredActivity.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -52,11 +51,15 @@ public class RequiredActivity extends RequiredComponent {
return userPackageManager.queryIntentActivities(intent, flags);
}
+ @Override
+ protected boolean isComponentQualified(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo.exported;
+ }
+
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo;
}
@Override
@@ -69,10 +72,4 @@ public class RequiredActivity extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.activityInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.activityInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
index 945fda3c3..1e23af256 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredBroadcastReceiver.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,9 +52,8 @@ public class RequiredBroadcastReceiver extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.activityInfo;
}
@Override
@@ -68,10 +66,4 @@ public class RequiredBroadcastReceiver extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.activityInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.activityInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
index ae6156e7f..f1ef50209 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredComponent.java
@@ -20,6 +20,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
@@ -108,9 +109,9 @@ public abstract class RequiredComponent {
* @return whether this required component is available
*/
public boolean isAvailable() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinTargetSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinTargetSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinTargetSdkVersion;
}
@@ -195,6 +196,10 @@ public abstract class RequiredComponent {
for (int resolveInfosIndex = 0; resolveInfosIndex < resolveInfosSize; resolveInfosIndex++) {
ResolveInfo resolveInfo = resolveInfos.get(resolveInfosIndex);
+ if (!isComponentQualified(resolveInfo)) {
+ continue;
+ }
+
if (mFlags != 0) {
int componentFlags = getComponentFlags(resolveInfo);
if ((componentFlags & mFlags) != mFlags) {
@@ -209,8 +214,9 @@ public abstract class RequiredComponent {
}
}
+ ComponentInfo componentInfo = getComponentComponentInfo(resolveInfo);
if (hasMetaData) {
- Bundle componentMetaData = getComponentMetaData(resolveInfo);
+ Bundle componentMetaData = componentInfo.metaData;
if (componentMetaData == null) {
componentMetaData = Bundle.EMPTY;
}
@@ -229,13 +235,14 @@ public abstract class RequiredComponent {
}
}
- ComponentName componentName = getComponentComponentName(resolveInfo);
- String componentPackageName = componentName.getPackageName();
+ String componentPackageName = componentInfo.packageName;
if (componentPackageNames.contains(componentPackageName)) {
continue;
}
-
componentPackageNames.add(componentPackageName);
+
+ ComponentName componentName = new ComponentName(componentPackageName,
+ componentInfo.name);
componentNames.add(componentName);
}
return componentNames;
@@ -256,15 +263,19 @@ public abstract class RequiredComponent {
protected abstract List<ResolveInfo> queryIntentComponentsAsUser(@NonNull Intent intent,
int flags, @NonNull UserHandle user, @NonNull Context context);
+ protected boolean isComponentQualified(@NonNull ResolveInfo resolveInfo) {
+ return true;
+ }
+
/**
- * Get the {@code ComponentName} of a component.
+ * Get the {@code ComponentInfo} of a component.
*
* @param resolveInfo the {@code ResolveInfo} of the component
*
- * @return the {@code ComponentName} of the component
+ * @return the {@code ComponentInfo} of the component
*/
@NonNull
- protected abstract ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo);
+ protected abstract ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo);
/**
* Get the flags that have been set on a component.
@@ -285,16 +296,6 @@ public abstract class RequiredComponent {
@Nullable
protected abstract String getComponentPermission(@NonNull ResolveInfo resolveInfo);
- /**
- * Get the meta data associated with a component.
- *
- * @param resolveInfo the {@code ResolveInfo} of the component
- *
- * @return the meta data associated with a component
- */
- @Nullable
- protected abstract Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo);
-
@Override
public String toString() {
return "RequiredComponent{"
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
index 7b53a25bb..b02062b11 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredContentProvider.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,9 +52,8 @@ public class RequiredContentProvider extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.providerInfo.packageName,
- resolveInfo.providerInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.providerInfo;
}
@Override
@@ -70,10 +68,4 @@ public class RequiredContentProvider extends RequiredComponent {
//return resolveInfo.providerInfo.readPermission;
throw new UnsupportedOperationException();
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.providerInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
index f27aae013..0532e53b2 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/RequiredService.java
@@ -16,12 +16,11 @@
package com.android.role.controller.model;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
import android.os.UserHandle;
import androidx.annotation.NonNull;
@@ -53,8 +52,8 @@ public class RequiredService extends RequiredComponent {
@NonNull
@Override
- protected ComponentName getComponentComponentName(@NonNull ResolveInfo resolveInfo) {
- return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+ protected ComponentInfo getComponentComponentInfo(@NonNull ResolveInfo resolveInfo) {
+ return resolveInfo.serviceInfo;
}
@Override
@@ -67,10 +66,4 @@ public class RequiredService extends RequiredComponent {
protected String getComponentPermission(@NonNull ResolveInfo resolveInfo) {
return resolveInfo.serviceInfo.permission;
}
-
- @Nullable
- @Override
- protected Bundle getComponentMetaData(@NonNull ResolveInfo resolveInfo) {
- return resolveInfo.serviceInfo.metaData;
- }
}
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
index aa6cba169..1d01fde58 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
@@ -392,9 +392,9 @@ public class Role {
* @return whether this role is available based on SDK version
*/
boolean isAvailableBySdkVersion() {
- // Workaround to match the value 34+ for U+ in roles.xml before SDK finalization.
- if (mMinSdkVersion >= 34) {
- return SdkLevel.isAtLeastU();
+ // Workaround to match the value 35+ for V+ in roles.xml before SDK finalization.
+ if (mMinSdkVersion >= 35) {
+ return SdkLevel.isAtLeastV();
} else {
return Build.VERSION.SDK_INT >= mMinSdkVersion
&& Build.VERSION.SDK_INT <= mMaxSdkVersion;
diff --git a/PermissionController/src/com/android/permissioncontroller/Constants.java b/PermissionController/src/com/android/permissioncontroller/Constants.java
index 58b62dc54..a063fb607 100644
--- a/PermissionController/src/com/android/permissioncontroller/Constants.java
+++ b/PermissionController/src/com/android/permissioncontroller/Constants.java
@@ -320,6 +320,17 @@ public class Constants {
*/
public static final String UNUSED_APPS_SAFETY_CENTER_SEE_UNUSED_APPS_ID = "see_unused_apps";
+ /**
+ * Fallback Settings package name
+ */
+ public static final String SETTINGS_PACKAGE_NAME_FALLBACK = "com.android.settings";
+
+ /**
+ * Extra launcher icon for notification
+ */
+ public static final String NOTIFICATION_EXTRA_USE_LAUNCHER_ICON =
+ "com.android.car.notification.EXTRA_USE_LAUNCHER_ICON";
+
// TODO(b/231624295) add to API
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public static final String OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO =
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/AutoSettingsFrameFragment.java b/PermissionController/src/com/android/permissioncontroller/auto/AutoSettingsFrameFragment.java
index 3b0e89b04..08e1b3560 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/AutoSettingsFrameFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/auto/AutoSettingsFrameFragment.java
@@ -27,6 +27,9 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.car.ui.FocusArea;
+import com.android.car.ui.R;
+import com.android.car.ui.baselayout.Insets;
import com.android.car.ui.preference.PreferenceFragment;
import com.android.car.ui.toolbar.MenuItem;
import com.android.car.ui.toolbar.ToolbarController;
@@ -56,6 +59,20 @@ public abstract class AutoSettingsFrameFragment extends PreferenceFragment {
return rootView;
}
+ @Override
+ public void onCarUiInsetsChanged(Insets insets) {
+ // don't allow scrolling behind the toolbar to be consistent with the rest of Settings
+ // reference UI. Scrolling behind toolbar also leads to flakier tests due to UI being
+ // visible but clicks are intercepted and dropped by the toolbar.
+ FocusArea focusArea = getView().findViewById(R.id.car_ui_focus_area);
+ focusArea.setHighlightPadding(
+ /* left= */ 0, /* top= */ 0, /* right= */ 0, /* bottom= */ 0);
+ focusArea.setBoundsOffset(/* left= */ 0, /* top= */ 0, /* right= */ 0, /* bottom= */ 0);
+ getView().setPadding(
+ insets.getLeft(), insets.getTop(), insets.getRight(), insets.getBottom());
+ getCarUiRecyclerView().setPadding(
+ /* left= */ 0, /* top= */ 0, /* right= */ 0, /* bottom= */ 0);
+ }
/** Sets the header text of this fragment. */
public void setHeaderLabel(CharSequence label) {
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
index 0562afc0f..88d887327 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
@@ -24,16 +24,13 @@ 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
@@ -72,7 +69,6 @@ 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"
@@ -280,15 +276,9 @@ 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 settingsIcon = KotlinUtils.getSettingsIcon(application,
+ permissionReminders.first().user,
+ applicationContext.packageManager)
val b = Notification.Builder(this, Constants.PERMISSION_REMINDER_CHANNEL_ID)
.setContentTitle(title)
@@ -299,7 +289,7 @@ class DrivingDecisionReminderService : Service() {
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.addExtras(Bundle().apply {
- putBoolean("com.android.car.notification.EXTRA_USE_LAUNCHER_ICON", false)
+ putBoolean(Constants.NOTIFICATION_EXTRA_USE_LAUNCHER_ICON, false)
})
// Auto doesn't show icons for actions
.addAction(Notification.Action.Builder(/* icon= */ null,
@@ -312,12 +302,6 @@ 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
- }
-
private fun logNotificationPresented() {
PermissionControllerStatsLog.write(
PermissionControllerStatsLog.PERMISSION_REMINDER_NOTIFICATION_INTERACTED,
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
index 1f6b5272a..6a7f527c7 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/HibernationPolicy.kt
@@ -80,6 +80,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
@@ -99,6 +100,7 @@ import com.android.permissioncontroller.permission.data.get
import com.android.permissioncontroller.permission.data.getUnusedPackages
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
import com.android.permissioncontroller.permission.service.revokeAppPermissions
+import com.android.permissioncontroller.permission.utils.IPC
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.StringUtils
import com.android.permissioncontroller.permission.utils.Utils
@@ -113,8 +115,7 @@ import kotlinx.coroutines.launch
private const val LOG_TAG = "HibernationPolicy"
const val DEBUG_OVERRIDE_THRESHOLDS = false
-// TODO eugenesusla: temporarily enabled for extra logs during dogfooding
-const val DEBUG_HIBERNATION_POLICY = true || DEBUG_OVERRIDE_THRESHOLDS
+const val DEBUG_HIBERNATION_POLICY = false
private var SKIP_NEXT_RUN = false
@@ -841,7 +842,9 @@ class HibernationJobService : JobService() {
appsToHibernate, this@HibernationJobService, sessionId)
val unusedApps: Set<Pair<String, UserHandle>> = hibernatedApps + revokedApps
if (unusedApps.isNotEmpty()) {
- showUnusedAppsNotification(unusedApps.size, sessionId)
+ showUnusedAppsNotification(unusedApps.size,
+ sessionId,
+ Process.myUserHandle())
if (SdkLevel.isAtLeastT() &&
revokedApps.isNotEmpty() &&
getSystemService(SafetyCenterManager::class.java)!!.isSafetyCenterEnabled) {
@@ -861,7 +864,11 @@ class HibernationJobService : JobService() {
return true
}
- private suspend fun showUnusedAppsNotification(numUnused: Int, sessionId: Long) {
+ private fun showUnusedAppsNotification(
+ numUnused: Int,
+ sessionId: Long,
+ user: UserHandle
+ ) {
val notificationManager = getSystemService(NotificationManager::class.java)!!
val permissionReminderChannel = NotificationChannel(
@@ -889,6 +896,13 @@ class HibernationJobService : JobService() {
.setAutoCancel(true)
.setContentIntent(makeUnusedAppsIntent(this, sessionId))
val extras = Bundle()
+ if (DeviceUtils.isAuto(this)) {
+ val settingsIcon = KotlinUtils.getSettingsIcon(application,
+ user,
+ applicationContext.packageManager)
+ extras.putBoolean(Constants.NOTIFICATION_EXTRA_USE_LAUNCHER_ICON, false)
+ b.setLargeIcon(settingsIcon)
+ }
if (SdkLevel.isAtLeastT() &&
getSystemService(SafetyCenterManager::class.java)!!.isSafetyCenterEnabled) {
val notificationResources = KotlinUtils.getSafetyCenterNotificationResources(this)
@@ -909,8 +923,10 @@ class HibernationJobService : JobService() {
notificationManager.notify(HibernationJobService::class.java.simpleName,
Constants.UNUSED_APPS_NOTIFICATION_ID, b.build())
- // Preload the unused packages
- getUnusedPackages().getInitializedValue()
+ GlobalScope.launch(IPC) {
+ // Preload the unused packages
+ getUnusedPackages().getInitializedValue(staleOk = true)
+ }
}
override fun onStopJob(params: JobParameters?): Boolean {
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/hibernation/TEST_MAPPING
index 16ee9b47d..69a8f74be 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/TEST_MAPPING
@@ -5,6 +5,9 @@
"options": [
{
"include-filter": "android.hibernation.cts.AppHibernationIntegrationTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
index f4dfe233a..5aa07c232 100644
--- a/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
+++ b/PermissionController/src/com/android/permissioncontroller/hibernation/v31/HibernationController.kt
@@ -25,6 +25,7 @@ import android.os.Build
import android.os.UserHandle
import androidx.annotation.RequiresApi
import com.android.permissioncontroller.DumpableLog
+import com.android.permissioncontroller.permission.data.HibernatedPackagesLiveData
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
/**
@@ -94,6 +95,9 @@ class HibernationController(
hibernationManager.setHibernatingGlobally(pkgName, true)
globallyHibernatedApps.add(pkgName)
}
+ if (hibernatedApps.isNotEmpty()) {
+ HibernatedPackagesLiveData.update()
+ }
if (DEBUG_HIBERNATION) {
DumpableLog.i(LOG_TAG,
"Done hibernating apps $hibernatedApps \n " +
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/ConfirmationActivity.java b/PermissionController/src/com/android/permissioncontroller/incident/ConfirmationActivity.java
index 0a8196524..c4a02eda4 100644
--- a/PermissionController/src/com/android/permissioncontroller/incident/ConfirmationActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/incident/ConfirmationActivity.java
@@ -16,7 +16,6 @@
package com.android.permissioncontroller.incident;
-import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
@@ -38,15 +37,20 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import androidx.activity.ComponentActivity;
+
import com.android.modules.utils.build.SdkLevel;
+import com.android.permissioncontroller.DeviceUtils;
import com.android.permissioncontroller.R;
+import com.android.permissioncontroller.incident.wear.ConfirmationActivityWearViewHandler;
import java.util.ArrayList;
/**
* Confirmation dialog for approving an incident or bug report for sharing off the device.
*/
-public class ConfirmationActivity extends Activity implements OnClickListener, OnDismissListener {
+public class ConfirmationActivity extends ComponentActivity implements OnClickListener,
+ OnDismissListener {
private static final String TAG = "ConfirmationActivity";
/**
@@ -107,7 +111,16 @@ public class ConfirmationActivity extends Activity implements OnClickListener, O
// since we can't get proper approval. (Zero-length images or reasons means that
// we will proceed with the imageless consent dialog).
final IncidentManager incidentManager = getSystemService(IncidentManager.class);
- incidentManager.denyReport(getIntent().getData());
+ incidentManager.denyReport(uri);
+
+ if (DeviceUtils.isWear(this)) {
+ ConfirmationActivityWearViewHandler viewHandler =
+ new ConfirmationActivityWearViewHandler(this, incidentManager);
+ setContentView(viewHandler.createView());
+ viewHandler.updateViewModel(true, getString(R.string.incident_report_dialog_title),
+ getString(R.string.incident_report_error_dialog_text, appLabel), uri);
+ return;
+ }
// Show a message to the user saying... nevermind.
new AlertDialog.Builder(this)
@@ -125,6 +138,22 @@ public class ConfirmationActivity extends Activity implements OnClickListener, O
}
+ final String message = getString(R.string.incident_report_dialog_text,
+ appLabel,
+ formatting.getDate(pending.getTimestamp()),
+ formatting.getTime(pending.getTimestamp()),
+ appLabel);
+
+ if (DeviceUtils.isWear(this)) {
+ ConfirmationActivityWearViewHandler viewHandler =
+ new ConfirmationActivityWearViewHandler(this,
+ getSystemService(IncidentManager.class));
+ setContentView(viewHandler.createView());
+ viewHandler.updateViewModel(false, getString(R.string.incident_report_dialog_title),
+ message, uri);
+ return;
+ }
+
final View content = getLayoutInflater().inflate(R.layout.incident_confirmation,
null);
@@ -162,11 +191,6 @@ public class ConfirmationActivity extends Activity implements OnClickListener, O
reasonTextView.setText(spannable);
}
- final String message = getString(R.string.incident_report_dialog_text,
- appLabel,
- formatting.getDate(pending.getTimestamp()),
- formatting.getTime(pending.getTimestamp()),
- appLabel);
((TextView) content.findViewById(R.id.message)).setText(message);
final ArrayList<Drawable> images = details.getImages();
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/PendingList.java b/PermissionController/src/com/android/permissioncontroller/incident/PendingList.java
index dead300d7..7efb89849 100644
--- a/PermissionController/src/com/android/permissioncontroller/incident/PendingList.java
+++ b/PermissionController/src/com/android/permissioncontroller/incident/PendingList.java
@@ -40,7 +40,7 @@ import java.util.Set;
/**
* Represents the current list of pending records.
*/
-class PendingList {
+public class PendingList {
private static final String TAG = "PermissionController.incident";
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/wear/ConfirmationActivityWearViewHandler.java b/PermissionController/src/com/android/permissioncontroller/incident/wear/ConfirmationActivityWearViewHandler.java
new file mode 100644
index 000000000..272a87960
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/incident/wear/ConfirmationActivityWearViewHandler.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 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.incident.wear;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.IncidentManager;
+import android.view.View;
+
+import com.android.permissioncontroller.incident.PendingList;
+
+import kotlin.Unit;
+
+/**
+ * Wear-specific view handler for the confirmation activity.
+ */
+public class ConfirmationActivityWearViewHandler {
+
+ private final Activity mActivity;
+ private final IncidentManager mIncidentManager;
+ private WearConfirmationActivityViewModel mViewModel;
+
+ public ConfirmationActivityWearViewHandler(Activity activity, IncidentManager incidentManager) {
+ mActivity = activity;
+ mIncidentManager = incidentManager;
+ }
+
+ /**
+ * Creates and returns the view hierarchy that is managed by this view
+ * handler. This must be called before {@link #updateViewModel}.
+ */
+ public View createView() {
+ WearConfirmationActivityViewModelFactory factory =
+ new WearConfirmationActivityViewModelFactory();
+ mViewModel = factory.create(
+ WearConfirmationActivityViewModel.class);
+
+ return WearConfirmationScreenKt.createView(mActivity, mViewModel);
+ }
+
+ /**
+ * Updates the wear confirmation activity view model to reflect the specified state.
+ */
+ public void updateViewModel(boolean isDenyView, String dialogTitle, String message, Uri uri) {
+ mViewModel.getShowDialogLiveData().setValue(true);
+ mViewModel.getShowDenyReportLiveData().setValue(isDenyView);
+ WearConfirmationActivityViewModel.ContentArgs args =
+ new WearConfirmationActivityViewModel.ContentArgs(
+ dialogTitle,
+ message,
+ () -> {
+ mIncidentManager.denyReport(uri);
+ mActivity.finish();
+ return Unit.INSTANCE;
+ },
+ () -> {
+ mIncidentManager.approveReport(uri);
+ PendingList.getInstance().updateState(mActivity, 0);
+ mActivity.finish();
+ return Unit.INSTANCE;
+ },
+ () -> {
+ mIncidentManager.denyReport(uri);
+ PendingList.getInstance().updateState(mActivity, 0);
+ mActivity.finish();
+ return Unit.INSTANCE;
+ }
+ );
+ mViewModel.getContentArgsLiveData().setValue(args);
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationActivityViewModel.kt b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationActivityViewModel.kt
new file mode 100644
index 000000000..8d23b4319
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationActivityViewModel.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.incident.wear
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+class WearConfirmationActivityViewModel : ViewModel() {
+ /** A livedata which stores whether the incident/bug report dialog is visible. */
+ val showDialogLiveData = MutableLiveData<Boolean>()
+
+ /** A livedata which stores to whether to show the screen for deny report */
+ val showDenyReportLiveData = MutableLiveData<Boolean>()
+
+ /** A livedata which stores arguments for a confirmation section. */
+ var contentArgsLiveData = MutableLiveData<ContentArgs>()
+
+ data class ContentArgs(
+ // stores the incident/bug report title
+ val title: String,
+ // stores the incident/bug report message body
+ val message: String,
+ // this is a button shows only in a denied incident/bug report dialog
+ val onDenyClick: () -> Unit,
+ val onOkClick: () -> Unit,
+ val onCancelClick: () -> Unit,
+ )
+
+ init {
+ showDialogLiveData.value = false
+ showDenyReportLiveData.value = false
+ contentArgsLiveData.value = null
+ }
+}
+
+/**
+ * Factory for a WearConfirmationActivityViewModel
+ */
+class WearConfirmationActivityViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return WearConfirmationActivityViewModel() as T
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt
new file mode 100644
index 000000000..fa67c8b6c
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 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.incident.wear
+
+import android.app.Activity
+import android.view.View
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.platform.ComposeView
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import com.android.permissioncontroller.permission.ui.wear.elements.AlertDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.SingleButtonAlertDialog
+import androidx.compose.foundation.layout.Box
+import androidx.compose.ui.Modifier
+import androidx.wear.compose.material.CircularProgressIndicator
+import androidx.compose.ui.Alignment
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.setValue
+
+@Composable
+fun WearConfirmationScreen(viewModel: WearConfirmationActivityViewModel) {
+ // Wear screen doesn't show incident/bug report's optional reasons and images.
+ val showDialog = viewModel.showDialogLiveData.observeAsState(false)
+ val showDenyReport = viewModel.showDenyReportLiveData.observeAsState(false)
+ val contentArgs = viewModel.contentArgsLiveData.observeAsState(null)
+ var isLoading by rememberSaveable { mutableStateOf(true) }
+
+ Box(modifier = Modifier.fillMaxSize()) {
+ if (isLoading) {
+ CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
+ } else {
+ if (showDenyReport.value) {
+ contentArgs.value?.let {
+ SingleButtonAlertDialog(
+ showDialog = showDialog.value,
+ title = it.title,
+ message = it.message,
+ onButtonClick = it.onDenyClick,
+ scalingLazyListState = ScalingLazyListState(0)
+ )
+ }
+ return
+ }
+ contentArgs.value?.let {
+ AlertDialog(
+ showDialog = showDialog.value,
+ title = it.title,
+ message = it.message,
+ onOKButtonClick = it.onOkClick,
+ onCancelButtonClick = it.onCancelClick,
+ scalingLazyListState = ScalingLazyListState(0)
+ )
+ }
+ }
+ }
+
+ if (isLoading && showDialog.value) {
+ isLoading = false
+ }
+}
+
+fun createView(
+ activity: Activity,
+ viewModel: WearConfirmationActivityViewModel
+): View {
+ return ComposeView(activity).apply {
+ setContent { WearConfirmationScreen(viewModel) }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
index b65eb6710..38d46fe76 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/permission/TEST_MAPPING
@@ -22,7 +22,7 @@
"include-filter": "android.permission.cts.PlatformPermissionGroupMappingTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
},
@@ -30,7 +30,7 @@
"name": "CtsHibernationTestCases",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
@@ -58,19 +58,77 @@
"include-filter": "android.permission.cts.PlatformPermissionGroupMappingTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
},
{
"name": "CtsHibernationTestCases[com.google.android.permission.apex]",
"options": [
- // TODO(b/238677038): This test currently fails on R base image
{
- "exclude-filter": "android.hibernation.cts.AutoRevokeTest#testUnusedApp_uninstallApp"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsHibernationTestCases"
+ },
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.LocationAccessCheckTest"
+ },
+ {
+ "include-filter": "android.permission.cts.NotificationListenerCheckTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "include-filter": "android.permission.cts.OneTimePermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionControllerTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PlatformPermissionGroupMappingTest"
+ }
+ ]
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsPermissionTestCases[com.google.android.permission.apex]",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.LocationAccessCheckTest"
+ },
+ {
+ "include-filter": "android.permission.cts.NotificationListenerCheckTest"
+ },
+ {
+ "include-filter": "android.permission.cts.OneTimePermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionControllerTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PlatformPermissionGroupMappingTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsHibernationTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677038): This test currently fails on R base image
+ {
+ "exclude-filter": "android.hibernation.cts.AutoRevokeTest#testUnusedApp_uninstallApp"
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java b/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java
deleted file mode 100644
index 637eb5fc4..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompat.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2023 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.compat;
-
-import android.text.Layout;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.method.LinkMovementMethod;
-import android.text.method.Touch;
-import android.view.MotionEvent;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-
-/**
- * Fixes the issue that links can be triggered for touches outside of line bounds for
- * {@link LinkMovementMethod}.
- * <p>
- * This is based on the fix in ag/22301465.
- */
-public class LinkMovementMethodCompat extends LinkMovementMethod {
- @Override
- public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer,
- @NonNull MotionEvent event) {
- int action = event.getAction();
-
- if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
- int x = (int) event.getX();
- int y = (int) event.getY();
-
- x -= widget.getTotalPaddingLeft();
- y -= widget.getTotalPaddingTop();
-
- x += widget.getScrollX();
- y += widget.getScrollY();
-
- Layout layout = widget.getLayout();
- boolean isOutOfLineBounds;
- if (y < 0 || y > layout.getHeight()) {
- isOutOfLineBounds = true;
- } else {
- int line = layout.getLineForVertical(y);
- isOutOfLineBounds = x < layout.getLineLeft(line) || x > layout.getLineRight(line);
- }
-
- if (isOutOfLineBounds) {
- Selection.removeSelection(buffer);
-
- // return LinkMovementMethod.super.onTouchEvent(widget, buffer, event);
- return Touch.onTouchEvent(widget, buffer, event);
- }
- }
-
- return super.onTouchEvent(widget, buffer, event);
- }
-
- /**
- * @return a {@link LinkMovementMethodCompat} instance
- */
- @NonNull
- public static LinkMovementMethodCompat getInstance() {
- if (sInstance == null) {
- sInstance = new LinkMovementMethodCompat();
- }
-
- return sInstance;
- }
-
- private static LinkMovementMethodCompat sInstance;
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
index b9d2d237a..7c69d6078 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt
@@ -62,6 +62,7 @@ class AppPermGroupUiInfoLiveData private constructor(
private val permGroupLiveData = PermGroupLiveData[permGroupName]
private val permissionStateLiveData = PermStateLiveData[packageName, permGroupName, user]
private val isStorage = permGroupName == STORAGE
+ private val isHealth = Utils.isHealthPermissionGroup(permGroupName)
init {
isSpecialLocation = LocationUtils.isLocationGroupAndProvider(app,
@@ -127,7 +128,8 @@ class AppPermGroupUiInfoLiveData private constructor(
val shouldShow = packageInfo.enabled &&
isGrantableAndNotLegacyPlatform(packageInfo, groupInfo, requestedPermissionInfos) &&
- (!isStorage || Utils.shouldShowStorage(packageInfo))
+ (!isStorage || Utils.shouldShowStorage(packageInfo)) &&
+ (!isHealth || Utils.shouldShowHealthPermission(packageInfo, groupInfo.name))
val isSystemApp = !isUserSensitive(permissionState)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
index 606562641..f764988c7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/HibernationSettingStateLiveData.kt
@@ -34,6 +34,7 @@ import com.android.permissioncontroller.hibernation.isPackageHibernationExemptBy
import com.android.permissioncontroller.hibernation.isPackageHibernationExemptByUser
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData.Companion.NON_RUNTIME_NORMAL_PERMS
import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
+import com.android.permissioncontroller.permission.service.AUTO_REVOKE_EXEMPT_PERMISSIONS
import kotlinx.coroutines.Job
/**
@@ -117,7 +118,10 @@ class HibernationSettingStateLiveData private constructor(
permState.permFlags and (FLAG_PERMISSION_GRANTED_BY_DEFAULT or
FLAG_PERMISSION_GRANTED_BY_ROLE) != 0
} ?: false
- if (!default) {
+ val allExempt = liveData.value?.all { (permName, _) ->
+ permName in AUTO_REVOKE_EXEMPT_PERMISSIONS
+ } ?: false
+ if (!default && !allExempt) {
revocableGroups.add(groupName)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
index 7c3ebe0b3..7abec470e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/SmartUpdateMediatorLiveData.kt
@@ -40,7 +40,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
MediatorLiveData<T>(), DataRepository.InactiveTimekeeper {
companion object {
- const val DEBUG_UPDATES = false
+ const val DEBUG = false
val LOG_TAG = SmartUpdateMediatorLiveData::class.java.simpleName
}
@@ -86,7 +86,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
*/
@MainThread
fun update() {
- if (DEBUG_UPDATES) {
+ if (DEBUG) {
Log.i(LOG_TAG, "update ${javaClass.simpleName} ${shortStackTrace()}")
}
@@ -115,15 +115,20 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
}
override fun <S : Any?> addSource(source: LiveData<S>, onChanged: Observer<in S>) {
- addSourceWithStackTraceAttribution(source, onChanged,
- IllegalStateException().getStackTrace())
+ addSourceWithStackTraceAttribution(source, onChanged)
}
private fun <S : Any?> addSourceWithStackTraceAttribution(
source: LiveData<S>,
- onChanged: Observer<in S>,
- stackTrace: Array<StackTraceElement>
+ onChanged: Observer<in S>
) {
+ val stackTrace =
+ if (DEBUG) {
+ IllegalStateException().stackTrace
+ } else {
+ null
+ }
+
GlobalScope.launch(Main.immediate) {
if (source is SmartUpdateMediatorLiveData) {
if (source in sources) {
@@ -134,7 +139,9 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
try {
super.addSource(source, onChanged)
} catch (ex: IllegalStateException) {
- ex.setStackTrace(stackTrace)
+ if (DEBUG) {
+ ex.stackTrace = stackTrace!!
+ }
throw ex
}
}
@@ -167,7 +174,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
have: MutableMap<K, V>,
getLiveDataFun: (K) -> V,
onUpdateFun: ((K) -> Unit)? = null
- ): Pair<Set<K>, Set<K>>{
+ ): Pair<Set<K>, Set<K>> {
// Ensure the map is correct when method returns
val (toAdd, toRemove) = KotlinUtils.getMapAndListDifferences(desired, have)
for (key in toAdd) {
@@ -176,8 +183,6 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
val removed = toRemove.map { have.remove(it) }.toMutableList()
- val stackTrace = IllegalStateException().getStackTrace()
-
GlobalScope.launch(Main.immediate) {
// If any state got out of sorts before this coroutine ran, correct it
for (key in toRemove) {
@@ -199,7 +204,7 @@ abstract class SmartUpdateMediatorLiveData<T>(private val isStaticVal: Boolean =
update()
}
}
- addSourceWithStackTraceAttribution(liveData, observer, stackTrace)
+ addSourceWithStackTraceAttribution(liveData, observer)
}
}
return toAdd to toRemove
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
index e096a1a7e..3b2cc7ee0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/AppPermissionGroup.java
@@ -56,6 +56,7 @@ import com.android.permissioncontroller.PermissionControllerApplication;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.service.LocationAccessCheck;
import com.android.permissioncontroller.permission.utils.ArrayUtils;
+import com.android.permissioncontroller.permission.utils.ContextCompat;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.LocationUtils;
import com.android.permissioncontroller.permission.utils.PermissionMapping;
@@ -336,8 +337,14 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
continue;
}
- final boolean granted = (packageInfo.requestedPermissionsFlags[i]
- & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
+ boolean granted;
+ if (ContextCompat.getDeviceId(context) == ContextCompat.DEVICE_ID_DEFAULT) {
+ granted = (packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
+ } else {
+ int result = packageManager.checkPermission(requestedPermission, packageName);
+ granted = result == PackageManager.PERMISSION_GRANTED;
+ }
final String appOp = PLATFORM_PACKAGE_NAME.equals(requestedPermissionInfo.packageName)
|| (isHealthPermissionUiEnabled() && HEALTH_PERMISSION_GROUP.equals(
@@ -936,8 +943,12 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
}
boolean wasGranted = permission.isGrantedIncludingAppOp();
+ boolean isPermissionSplitFromNonRuntime = KotlinUtils.isPermissionSplitFromNonRuntime(
+ mContext,
+ permission.getName(),
+ mPackageInfo.applicationInfo.targetSdkVersion);
- if (mAppSupportsRuntimePermissions) {
+ if (mAppSupportsRuntimePermissions && !isPermissionSplitFromNonRuntime) {
// Do not touch permissions fixed by the system.
if (permission.isSystemFixed()) {
wasAllGranted = false;
@@ -1127,7 +1138,14 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
boolean wasGranted = permission.isGrantedIncludingAppOp();
- if (mAppSupportsRuntimePermissions) {
+ boolean isPermissionSplitFromNonRuntime =
+ KotlinUtils.isPermissionSplitFromNonRuntime(
+ mContext,
+ permission.getName(),
+ mPackageInfo.applicationInfo.targetSdkVersion);
+
+ if (mAppSupportsRuntimePermissions && !isPermissionSplitFromNonRuntime) {
+
// Revoke the permission if needed.
if (permission.isGranted()) {
permission.setGranted(false);
@@ -1172,6 +1190,8 @@ public final class AppPermissionGroup implements Comparable<AppPermissionGroup>
if (!permission.isRevokedCompat()) {
permission.setRevokedCompat(true);
}
+
+ permission.setRevokeWhenRequested(false);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java b/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
index 5ddea4605..4daaeaec8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/Permission.java
@@ -169,6 +169,18 @@ public final class Permission {
}
/**
+ * Sets the REVOKE_WHEN_REQUESTED permission flag
+ * @param revokeWhenRequested true to set the flag, false to unset it
+ */
+ public void setRevokeWhenRequested(boolean revokeWhenRequested) {
+ if (revokeWhenRequested) {
+ mFlags |= PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+ } else {
+ mFlags &= ~PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+ }
+ }
+
+ /**
* Sets the one-time permission flag
* @param oneTime true to set the flag, false to unset it
*/
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
index 0f6b6c000..caa05d1fb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt
@@ -61,14 +61,14 @@ data class LightPackageInfo(
pI.permissions?.map { perm -> LightPermInfo(perm) } ?: emptyList(),
pI.requestedPermissions?.toList() ?: emptyList(),
pI.requestedPermissionsFlags?.toList() ?: emptyList(),
- pI.applicationInfo.uid,
- pI.applicationInfo.targetSdkVersion,
- pI.applicationInfo.isInstantApp,
- pI.applicationInfo.enabled,
- pI.applicationInfo.flags,
+ pI.applicationInfo!!.uid,
+ pI.applicationInfo!!.targetSdkVersion,
+ pI.applicationInfo!!.isInstantApp,
+ pI.applicationInfo!!.enabled,
+ pI.applicationInfo!!.flags,
pI.firstInstallTime,
pI.lastUpdateTime,
- if (SdkLevel.isAtLeastS()) pI.applicationInfo.areAttributionsUserVisible() else false,
+ if (SdkLevel.isAtLeastS()) pI.applicationInfo!!.areAttributionsUserVisible() else false,
if (SdkLevel.isAtLeastS()) buildAttributionTagsToLabelsMap(pI.attributions) else emptyMap())
/** Permissions which are granted according to the [requestedPermissionsFlags] */
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
index ae9ccf19e..6b28f68f6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/AutoRevokePermissions.kt
@@ -33,6 +33,7 @@ import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_
import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_UNUSED_APP_PERMISSION_REVOKED
import com.android.permissioncontroller.hibernation.getUnusedThresholdMs
import com.android.permissioncontroller.permission.utils.PermissionMapping
+import com.android.permissioncontroller.permission.data.AutoRevokedPackagesLiveData
import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData
import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData
import com.android.permissioncontroller.permission.data.get
@@ -48,7 +49,7 @@ import java.util.concurrent.atomic.AtomicBoolean
private const val LOG_TAG = "AutoRevokePermissions"
const val DEBUG_AUTO_REVOKE = true
-private val EXEMPT_PERMISSIONS = listOf(
+val AUTO_REVOKE_EXEMPT_PERMISSIONS = listOf(
Manifest.permission.ACTIVITY_RECOGNITION,
Manifest.permission.POST_NOTIFICATIONS)
@@ -83,6 +84,9 @@ suspend fun revokeAppPermissions(
// For each autorevoke-eligible app...
userApps.forEachInParallel(Main) forEachInParallelOuter@ { pkg: LightPackageInfo ->
if (pkg.grantedPermissions.isEmpty()) {
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "${pkg.packageName}: no granted permissions")
+ }
return@forEachInParallelOuter
}
val packageName = pkg.packageName
@@ -96,9 +100,20 @@ suspend fun revokeAppPermissions(
return@forEachInParallelOuter
}
val targetSdk = pkg.targetSdkVersion
- val pkgPermGroups: Map<String, List<String>> =
+ val pkgPermGroups: Map<String, List<String>>? =
PackagePermissionsLiveData[packageName, user]
- .getInitializedValue() ?: return@forEachInParallelOuter
+ .getInitializedValue()
+
+ if (pkgPermGroups == null || pkgPermGroups.isEmpty()) {
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "$packageName: no permission groups found.")
+ }
+ return@forEachInParallelOuter
+ }
+
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "$packageName: perm groups: ${pkgPermGroups.keys}.")
+ }
// Determine which permGroups are revocable
val revocableGroups = mutableSetOf<String>()
@@ -114,7 +129,7 @@ suspend fun revokeAppPermissions(
.getInitializedValue() ?: continue
val fixed = group.isBackgroundFixed || group.isForegroundFixed
val granted = group.permissions.any { (_, perm) ->
- perm.isGrantedIncludingAppOp && perm.name !in EXEMPT_PERMISSIONS
+ perm.isGrantedIncludingAppOp && perm.name !in AUTO_REVOKE_EXEMPT_PERMISSIONS
}
if (!fixed && granted &&
!group.isGrantedByDefault &&
@@ -125,6 +140,10 @@ suspend fun revokeAppPermissions(
}
}
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "$packageName: initial revocable groups: $revocableGroups")
+ }
+
// Mark any groups that split from an install-time permission as unrevocable
for (fromPerm in
pkgPermGroups[PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS] ?: emptyList()) {
@@ -148,6 +167,9 @@ suspend fun revokeAppPermissions(
}
}
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "$packageName: final revocable groups: $revocableGroups")
+ }
// For each revocable group, revoke all of its permissions
val anyPermsRevoked = AtomicBoolean(false)
pkgPermGroups.entries
@@ -160,6 +182,9 @@ suspend fun revokeAppPermissions(
val revocablePermissions = group.permissions.keys.toList()
if (revocablePermissions.isEmpty()) {
+ if (DEBUG_AUTO_REVOKE) {
+ DumpableLog.i(LOG_TAG, "$packageName: revocable permissions empty")
+ }
return@forEachInParallelInner
}
@@ -221,5 +246,8 @@ suspend fun revokeAppPermissions(
}
}
}
+ if (revokedApps.isNotEmpty()) {
+ AutoRevokedPackagesLiveData.update()
+ }
return revokedApps
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java b/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
index 9082b6931..39e289fd2 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/BackupHelper.java
@@ -136,8 +136,8 @@ public class BackupHelper {
case END_TAG:
numOpenTags--;
break;
- default:
- // ignore
+ case END_DOCUMENT:
+ return;
}
}
}
@@ -763,8 +763,6 @@ public class BackupHelper {
return new BackupSigningInfoState(
currentCertDigests,
pastCertDigests);
- default:
- throw new XmlPullParserException("Could not parse signing info");
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/LocationAccessCheck.java b/PermissionController/src/com/android/permissioncontroller/permission/service/LocationAccessCheck.java
index e21be6a05..0b433684a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/LocationAccessCheck.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/LocationAccessCheck.java
@@ -41,6 +41,9 @@ import static android.os.UserHandle.getUserHandleForUid;
import static android.os.UserHandle.myUserId;
import static android.provider.Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS;
import static android.provider.Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS;
+import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID;
+import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID;
+import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_HANDLE;
import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
@@ -75,6 +78,7 @@ import static java.util.concurrent.TimeUnit.DAYS;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
+import android.app.Application;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -123,6 +127,8 @@ import androidx.annotation.WorkerThread;
import androidx.core.util.Preconditions;
import com.android.modules.utils.build.SdkLevel;
+import com.android.permissioncontroller.Constants;
+import com.android.permissioncontroller.DeviceUtils;
import com.android.permissioncontroller.PermissionControllerStatsLog;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
@@ -410,7 +416,7 @@ public class LocationAccessCheck {
private void addLocationNotificationIfNeeded(@NonNull JobParameters params,
@NonNull LocationAccessCheckJobService service) {
if (!checkLocationAccessCheckEnabledAndUpdateEnabledTime()) {
- Log.v(LOG_TAG, "LocationAccessCheck feature is not enabled.");
+ Log.i(LOG_TAG, "LocationAccessCheck feature is not enabled.");
service.jobFinished(params, false);
return;
}
@@ -420,19 +426,19 @@ public class LocationAccessCheck {
if (currentTimeMillis() - mSharedPrefs.getLong(
KEY_LAST_LOCATION_ACCESS_NOTIFICATION_SHOWN, 0)
< getInBetweenNotificationsMillis()) {
- Log.v(LOG_TAG, "location notification interval is not enough.");
+ Log.i(LOG_TAG, "location notification interval is not enough.");
service.jobFinished(params, false);
return;
}
if (getCurrentlyShownNotificationLocked() != null) {
- Log.v(LOG_TAG, "already location notification exist.");
+ Log.i(LOG_TAG, "already location notification exist.");
service.jobFinished(params, false);
return;
}
addLocationNotificationIfNeeded(mAppOpsManager.getPackagesForOps(
- new String[]{OPSTR_FINE_LOCATION}));
+ new String[]{OPSTR_FINE_LOCATION}), service.getApplication());
service.jobFinished(params, false);
} catch (Exception e) {
Log.e(LOG_TAG, "Could not check for location access", e);
@@ -440,20 +446,19 @@ public class LocationAccessCheck {
} finally {
synchronized (sLock) {
service.mAddLocationNotificationIfNeededTask = null;
- Log.v(LOG_TAG, "LocationAccessCheck privacy job marked complete.");
}
}
}
}
- private void addLocationNotificationIfNeeded(@NonNull List<PackageOps> ops)
+ private void addLocationNotificationIfNeeded(@NonNull List<PackageOps> ops, Application app)
throws InterruptedException {
synchronized (sLock) {
List<UserPackage> packages = getLocationUsersLocked(ops);
ArraySet<UserPackage> alreadyNotifiedPackages = loadAlreadyNotifiedPackagesLocked();
if (DEBUG) {
- Log.v(LOG_TAG, "location packages: " + packages);
- Log.v(LOG_TAG, "already notified packages: " + alreadyNotifiedPackages);
+ Log.d(LOG_TAG, "location packages: " + packages);
+ Log.d(LOG_TAG, "already notified packages: " + alreadyNotifiedPackages);
}
throwInterruptedExceptionIfTaskIsCanceled();
// Send these issues to safety center
@@ -471,7 +476,7 @@ public class LocationAccessCheck {
if (packages.isEmpty()) {
if (DEBUG) {
- Log.v(LOG_TAG, "No package found to send a notification");
+ Log.d(LOG_TAG, "No package found to send a notification");
}
return;
}
@@ -503,7 +508,7 @@ public class LocationAccessCheck {
}
}
createPermissionReminderChannel(getUserHandleForUid(pkgInfo.applicationInfo.uid));
- createNotificationForLocationUser(pkgInfo);
+ createNotificationForLocationUser(pkgInfo, app);
}
}
@@ -639,7 +644,7 @@ public class LocationAccessCheck {
*
* @param pkg The {@link PackageInfo} for the package to to be changed
*/
- private void createNotificationForLocationUser(@NonNull PackageInfo pkg) {
+ private void createNotificationForLocationUser(@NonNull PackageInfo pkg, Application app) {
CharSequence pkgLabel = mPackageManager.getApplicationLabel(pkg.applicationInfo);
boolean safetyCenterBgLocationReminderEnabled = isSafetyCenterBgLocationReminderEnabled();
@@ -707,20 +712,27 @@ public class LocationAccessCheck {
b.setLargeIcon(pkgIconBmp);
}
+ Bundle extras = new Bundle();
+ if (DeviceUtils.isAuto(mContext)) {
+ Bitmap settingsIcon = KotlinUtils.INSTANCE.getSettingsIcon(app, user, mPackageManager);
+ b.setLargeIcon(settingsIcon);
+ extras.putBoolean(Constants.NOTIFICATION_EXTRA_USE_LAUNCHER_ICON, false);
+ }
+
if (!TextUtils.isEmpty(appLabel)) {
- Bundle extras = new Bundle();
String appNameSubstitute = appLabel.toString();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appNameSubstitute);
- b.addExtras(extras);
}
+ b.addExtras(extras);
notificationManager.notify(pkgName, LOCATION_ACCESS_CHECK_NOTIFICATION_ID, b.build());
markAsNotified(pkgName, user, false);
- if (DEBUG) Log.i(LOG_TAG, "Notified " + pkgName);
-
- Log.v(LOG_TAG, "Location access check notification shown with sessionId=" + sessionId + ""
- + " uid=" + pkg.applicationInfo.uid + " pkgName=" + pkgName);
+ if (DEBUG) {
+ Log.d(LOG_TAG,
+ "Location access check notification shown with sessionId=" + sessionId + ""
+ + " uid=" + pkg.applicationInfo.uid + " pkgName=" + pkgName);
+ }
if (safetyCenterBgLocationReminderEnabled) {
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION,
@@ -1054,6 +1066,10 @@ public class LocationAccessCheck {
Intent clickIntent = null;
if (isSafetyCenterBgLocationReminderEnabled()) {
clickIntent = new Intent(ACTION_SAFETY_CENTER);
+ clickIntent.putExtra(EXTRA_SAFETY_SOURCE_ID, BG_LOCATION_SOURCE_ID);
+ clickIntent.putExtra(
+ EXTRA_SAFETY_SOURCE_ISSUE_ID, createSafetySourceIssueId(pkg, user));
+ clickIntent.putExtra(EXTRA_SAFETY_SOURCE_USER_HANDLE, user);
} else {
clickIntent = new Intent(ACTION_MANAGE_APP_PERMISSION);
clickIntent.putExtra(EXTRA_PERMISSION_GROUP_NAME, LOCATION);
@@ -1159,7 +1175,6 @@ public class LocationAccessCheck {
@Override
public void onCreate() {
- Log.v(LOG_TAG, "LocationAccessCheck privacy job is created");
super.onCreate();
mLocationAccessCheck = new LocationAccessCheck(this, () -> {
synchronized (sLock) {
@@ -1178,10 +1193,9 @@ public class LocationAccessCheck {
*/
@Override
public boolean onStartJob(JobParameters params) {
- Log.v(LOG_TAG, "LocationAccessCheck privacy job is started");
synchronized (LocationAccessCheck.sLock) {
if (mAddLocationNotificationIfNeededTask != null) {
- Log.v(LOG_TAG, "LocationAccessCheck old job not completed yet.");
+ Log.i(LOG_TAG, "LocationAccessCheck old job not completed yet.");
return false;
}
@@ -1202,7 +1216,6 @@ public class LocationAccessCheck {
*/
@Override
public boolean onStopJob(JobParameters params) {
- Log.v(LOG_TAG, "LocationAccessCheck privacy source onStopJob called.");
AddLocationNotificationIfNeededTask task;
synchronized (sLock) {
if (mAddLocationNotificationIfNeededTask == null) {
@@ -1250,7 +1263,7 @@ public class LocationAccessCheck {
long sessionId = intent.getLongExtra(EXTRA_SESSION_ID, INVALID_SESSION_ID);
int uid = intent.getIntExtra(EXTRA_UID, -1);
- Log.v(LOG_TAG,
+ Log.i(LOG_TAG,
"Location access check notification declined with sessionId=" + sessionId + ""
+ " uid=" + uid + " pkgName=" + pkg);
LocationAccessCheck locationAccessCheck = new LocationAccessCheck(context, null);
@@ -1325,7 +1338,7 @@ public class LocationAccessCheck {
UserHandle user = getParcelableExtraSafe(intent, EXTRA_USER);
long sessionId = intent.getLongExtra(EXTRA_SESSION_ID, INVALID_SESSION_ID);
int uid = intent.getIntExtra(EXTRA_UID, -1);
- Log.v(LOG_TAG,
+ Log.i(LOG_TAG,
"Location access check warning card dismissed with sessionId=" + sessionId + ""
+ " uid=" + uid + " pkgName=" + pkg);
PermissionControllerStatsLog.write(
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
index d5c43335c..3e7ebfec0 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
@@ -30,6 +30,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import android.Manifest;
import android.app.admin.DevicePolicyManager;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -62,6 +63,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGr
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo.PermGrantState;
import com.android.permissioncontroller.permission.ui.AutoGrantPermissionsNotifier;
import com.android.permissioncontroller.permission.utils.ArrayUtils;
+import com.android.permissioncontroller.permission.utils.ContextCompat;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.PermissionMapping;
import com.android.permissioncontroller.permission.utils.UserSensitiveFlagsUtils;
@@ -641,7 +643,14 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
@Override
public void onOneTimePermissionSessionTimeout(@NonNull String packageName) {
- PackageManager pm = getPackageManager();
+ onOneTimePermissionSessionTimeout(packageName, ContextCompat.DEVICE_ID_DEFAULT);
+ }
+
+ @Override
+ public void onOneTimePermissionSessionTimeout(@NonNull String packageName,
+ int deviceId) {
+ Context deviceContext = ContextCompat.createDeviceContext(this, deviceId);
+ PackageManager pm = deviceContext.getPackageManager();
PackageInfo packageInfo;
int uid;
try {
@@ -655,11 +664,10 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
if (permissions == null) {
return;
}
-
Set<AppPermissionGroup> groups = new ArraySet<>();
for (String permission : permissions) {
- AppPermissionGroup group = AppPermissionGroup.create(this, packageInfo, permission,
- true);
+ AppPermissionGroup group = AppPermissionGroup.create(deviceContext, packageInfo,
+ permission, true);
if (group != null) {
AppPermissionGroup bgGroup = group.getBackgroundPermissions();
boolean isBgGroupOneTime = bgGroup != null && bgGroup.isOneTime();
@@ -730,7 +738,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
for (Permission permission : group.getPermissions()) {
if (permission.isGranted()) {
String permName = permission.getName();
- Log.v(LOG_TAG,
+ Log.i(LOG_TAG,
"Permission grant result requestId=" + requestId + " callingUid="
+ uid + " callingPackage=" + packageName + " permission="
+ permName + " isImplicit=false" + " result=" + r);
@@ -779,13 +787,21 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
@NonNull List<String> permissions, @NonNull Runnable callback) {
+ onRevokeSelfPermissionsOnKill(
+ packageName, permissions, ContextCompat.DEVICE_ID_DEFAULT, callback);
+ }
+
+ @Override
+ public void onRevokeSelfPermissionsOnKill(@NonNull String packageName,
+ @NonNull List<String> permissions, int deviceId, @NonNull Runnable callback) {
+ Context deviceContext = ContextCompat.createDeviceContext(this, deviceId);
PackageInfo pkgInfo = getPkgInfo(packageName);
if (pkgInfo == null) {
throw new SecurityException("Cannot revoke permission " + String.join(",", permissions)
+ " for package " + packageName);
}
Set<AppPermissionGroup> groups = new HashSet<>();
- AppPermissions app = new AppPermissions(this, pkgInfo, false, true, null);
+ AppPermissions app = new AppPermissions(deviceContext, pkgInfo, false, true, null);
for (String permName : permissions) {
AppPermissionGroup group = app.getGroupForPermission(permName);
if (group == null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
index 3405ab014..d8a89bb00 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt
@@ -42,6 +42,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightPerm
import com.android.permissioncontroller.permission.utils.IPC
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantForegroundRuntimePermissions
+import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.PermissionMapping.getPlatformPermissionNamesOfGroup
import com.android.permissioncontroller.permission.utils.PermissionMapping.getRuntimePlatformPermissionNames
import com.android.permissioncontroller.permission.utils.application
@@ -55,7 +56,9 @@ internal object RuntimePermissionsUpgradeController {
private val LOG_TAG = RuntimePermissionsUpgradeController::class.java.simpleName
// The latest version of the runtime permissions database
- private val LATEST_VERSION = if (SdkLevel.isAtLeastT()) {
+ private val LATEST_VERSION = if (SdkLevel.isAtLeastU()) {
+ 11
+ } else if (SdkLevel.isAtLeastT()) {
10
} else {
9
@@ -134,6 +137,7 @@ internal object RuntimePermissionsUpgradeController {
val needBackgroundAppPermGroups = sdkUpgradedFromP && currentVersion <= 6
val needAccessMediaAppPermGroups = !isNewUser && currentVersion <= 7
val needGrantedExternalStorage = currentVersion <= 9 && SdkLevel.isAtLeastT()
+ val needGrantedReadMediaVisual = currentVersion <= 10 && SdkLevel.isAtLeastU()
val isDeviceUpgrading = context.packageManager.isDeviceUpgrading
// All data needed by this method.
@@ -156,24 +160,17 @@ internal object RuntimePermissionsUpgradeController {
private val pkgInfoProvider = UserPackageInfosLiveData[myUserHandle()]
/** Provides all {@link LightAppPermGroup} this upgrade needs */
- private var permGroupProviders: MutableList<LightAppPermGroupLiveData>? = null
+ private var permGroupProviders: MutableSet<LightAppPermGroupLiveData>? = null
/** {@link #permGroupProviders} that already provided a result */
private val permGroupProvidersDone = mutableSetOf<LightAppPermGroupLiveData>()
init {
// First step: Load packages + perm infos
- // TODO ntmyren: remove once b/154796729 is fixed
- Log.i("RuntimePermissions", "observing UserPackageInfoLiveData for " +
- "${myUserHandle().identifier} in RuntimePermissionsUpgradeController")
addSource(pkgInfoProvider) { pkgInfos ->
if (pkgInfos != null) {
removeSource(pkgInfoProvider)
- // TODO ntmyren: remove once b/154796729 is fixed
- Log.i("RuntimePermissions", "observing " +
- "PreinstalledUserPackageInfoLiveData for ${myUserHandle().identifier}" +
- " in RuntimePermissionsUpgradeController")
addSource(preinstalledPkgInfoProvider) { preinstalledPkgInfos ->
if (preinstalledPkgInfos != null) {
removeSource(preinstalledPkgInfoProvider)
@@ -203,15 +200,16 @@ internal object RuntimePermissionsUpgradeController {
if (permGroupProviders == null && pkgInfoProvider.value != null) {
// Second step: Trigger load of app-perm-groups
- permGroupProviders = mutableListOf()
+ permGroupProviders = mutableSetOf()
// Only load app-perm-groups needed for this upgrade
if (needBackgroundAppPermGroups || needAccessMediaAppPermGroups ||
- needGrantedExternalStorage) {
+ needGrantedExternalStorage || needGrantedReadMediaVisual) {
for ((pkgName, _, requestedPerms, requestedPermFlags) in
pkgInfoProvider.value!!) {
var requestsAccessMediaLocation = false
var hasGrantedExternalStorage = false
+ var hasGrantedReadMediaVisual = false
for ((perm, flags) in requestedPerms.zip(requestedPermFlags)) {
if (needBackgroundAppPermGroups &&
@@ -220,17 +218,22 @@ internal object RuntimePermissionsUpgradeController {
permission_group.LOCATION, myUserHandle()])
}
- if (needAccessMediaAppPermGroups || needGrantedExternalStorage) {
+ if (needAccessMediaAppPermGroups || needGrantedExternalStorage ||
+ needGrantedReadMediaVisual) {
if (needAccessMediaAppPermGroups &&
perm == permission.ACCESS_MEDIA_LOCATION) {
requestsAccessMediaLocation = true
}
- if (perm == permission.READ_EXTERNAL_STORAGE &&
- flags and PackageInfo.REQUESTED_PERMISSION_GRANTED
- != 0) {
+ val isGranted =
+ flags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0
+ if (perm == permission.READ_EXTERNAL_STORAGE && isGranted) {
hasGrantedExternalStorage = true
}
+ if (PermissionMapping.getGroupOfPlatformPermission(perm)
+ == permission_group.READ_MEDIA_VISUAL && isGranted) {
+ hasGrantedReadMediaVisual = true
+ }
}
}
@@ -255,6 +258,10 @@ internal object RuntimePermissionsUpgradeController {
accessMediaLocationPermGroup, myUserHandle()])
}
}
+ if (hasGrantedReadMediaVisual && needGrantedReadMediaVisual) {
+ permGroupProviders!!.add(LightAppPermGroupLiveData[pkgName,
+ permission_group.READ_MEDIA_VISUAL, myUserHandle()])
+ }
}
}
@@ -536,6 +543,24 @@ internal object RuntimePermissionsUpgradeController {
currentVersion = 10
}
+ if (currentVersion == 10 && SdkLevel.isAtLeastU()) {
+ // On U, if the app is granted READ_MEDIA_VISUAL, expand the grant to
+ // READ_MEDIA_VISUAL_USER_SELECTED
+ if (isDeviceUpgrading && !isNewUser) {
+ Log.i(LOG_TAG, "Grandfathering READ_MEDIA_VISUAL_USER_SELECTED to apps already " +
+ "granted visual permissions")
+ val visualAppPermGroups = storageAndMediaAppPermGroups.filter {
+ it.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
+ it.permGroupInfo.name == permission_group.READ_MEDIA_VISUAL &&
+ it.isGranted && it.isUserSet
+ }
+ visualAppPermGroups.forEach {
+ grants.add(Grant(false, it))
+ }
+ }
+ currentVersion = 11
+ }
+
// XXX: Add new upgrade steps above this point.
return Triple(currentVersion, exemptions, grants)
@@ -591,7 +616,7 @@ internal object RuntimePermissionsUpgradeController {
private val isBackground: Boolean,
/** Group to be granted */
private val group: LightAppPermGroup,
- /** Which of th permissions in the group should be granted */
+ /** Which of the permissions in the group should be granted */
private val permissions: List<String> = group.permissions.keys.toList()
) {
/**
@@ -630,9 +655,9 @@ internal object RuntimePermissionsUpgradeController {
for (permName in filterPermissions) {
val permission = permissionGroup.permissions[permName] ?: continue
PermissionControllerStatsLog.write(RUNTIME_PERMISSIONS_UPGRADE_RESULT,
- permission.name, uid, packageName)
- Log.v(LOG_TAG, "Runtime permission upgrade logged for permissionName=" +
- permission.name + " uid=" + uid + " packageName=" + packageName)
+ permission.name, uid, packageName)
+ Log.i(LOG_TAG, "Runtime permission upgrade logged for permissionName=" +
+ permission.name + " uid=" + uid + " packageName=" + packageName)
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/service/TEST_MAPPING
index b8dd3d77a..5dea9615a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/TEST_MAPPING
@@ -4,21 +4,24 @@
"name": "CtsPermissionTestCases",
"options": [
{
- "include-filter": "android.permission.cts.PermissionControllerTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
},
{
- "include-filter": "android.permission.cts.OneTimePermissionTest"
+ "include-filter": "android.permission.cts.PermissionControllerTest"
},
{
- "exclude-annotation": "androidx.test.filters.FlakyTest"
+ "include-filter": "android.permission.cts.OneTimePermissionTest"
}
]
},
{
- "name": "CtsPermission3TestCases",
+ "name": "CtsPermissionUiTestCases",
"options": [
{
- "include-filter": "android.permission3.cts.SafetyLabelChangesJobServiceTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "include-filter": "android.permissionui.cts.SafetyLabelChangesJobServiceTest"
}
]
},
@@ -26,6 +29,9 @@
"name": "CtsPermissionTestCases",
"options": [
{
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
"include-filter": "android.permission.cts.LocationAccessCheckTest"
}
],
@@ -59,7 +65,7 @@
"include-annotation": "com.android.cts.devicepolicy.annotations.PermissionsTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
@@ -69,10 +75,43 @@
"name": "CtsPermissionTestCases",
"options": [
{
- "include-filter": "android.permission.cts.LocationAccessCheckTest"
+ "include-filter": "android.permission.cts.PermissionControllerTest"
},
{
- "exclude-annotation": "androidx.test.filters.FlakyTest"
+ "include-filter": "android.permission.cts.OneTimePermissionTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionUiTestCases",
+ "options": [
+ {
+ "include-filter": "android.permissionui.cts.SafetyLabelChangesJobServiceTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.LocationAccessCheckTest"
+ }
+ ],
+ "file_patterns": ["LocationAccessCheck\\.java"]
+ },
+ {
+ "name": "CtsBackupTestCases",
+ "options": [
+ {
+ "include-filter": "android.backup.cts.PermissionTest"
+ }
+ ]
+ },
+ {
+ "name": "PermissionControllerOutOfProcessTests",
+ "options": [
+ {
+ "include-filter": "com.android.permissioncontroller.tests.outofprocess.DumpTest"
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
index 61336cdce..5daf26883 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/Category.kt
@@ -24,5 +24,6 @@ enum class Category(val categoryName: String) {
ALLOWED("allowed"),
ALLOWED_FOREGROUND("allowed_foreground"),
ASK("ask"),
- DENIED("denied")
+ DENIED("denied"),
+ STORAGE_FOOTER("storage_footer_category"),
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index ff63cdae5..4b052a753 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -21,8 +21,8 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission_group.LOCATION;
import static android.Manifest.permission_group.READ_MEDIA_VISUAL;
import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.CANCELED;
import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED;
import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_DO_NOT_ASK_AGAIN;
@@ -40,6 +40,8 @@ import static com.android.permissioncontroller.permission.utils.Utils.getRequest
import android.Manifest;
import android.app.Activity;
import android.app.KeyguardManager;
+import android.companion.virtual.VirtualDevice;
+import android.companion.virtual.VirtualDeviceManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -49,6 +51,7 @@ import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
+import android.provider.Settings;
import android.text.Annotation;
import android.text.SpannableString;
import android.text.Spanned;
@@ -76,7 +79,10 @@ import com.android.permissioncontroller.permission.ui.auto.GrantPermissionsAutoV
import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel;
import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.RequestInfo;
import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModelFactory;
+import com.android.permissioncontroller.permission.ui.model.NewGrantPermissionsViewModel;
+import com.android.permissioncontroller.permission.ui.model.NewGrantPermissionsViewModelFactory;
import com.android.permissioncontroller.permission.ui.wear.GrantPermissionsWearViewHandler;
+import com.android.permissioncontroller.permission.utils.ContextCompat;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
@@ -149,6 +155,11 @@ public class GrantPermissionsActivity extends SettingsActivity
/** The current list of permissions requested, across all current requests for this app */
private List<String> mRequestedPermissions = new ArrayList<>();
+
+ /** A list of permissions requested on an app's behalf by the system. Usually Implicitly
+ * requested, although this isn't necessarily always the case.
+ */
+ private List<String> mSystemRequestedPermissions = new ArrayList<>();
/** A copy of the list of permissions originally requested in the intent to this activity */
private String[] mOriginalRequestedPermissions = new String[0];
@@ -172,7 +183,6 @@ public class GrantPermissionsActivity extends SettingsActivity
private String mTargetPackage;
/** A key representing this activity, defined by the target package and task ID */
private Pair<String, Integer> mKey;
- private int mCurrentRequestIdx = 0;
private float mOriginalDimAmount;
private View mRootView;
private int mStoragePermGroupIcon = R.drawable.ic_empty_icon;
@@ -191,6 +201,10 @@ public class GrantPermissionsActivity extends SettingsActivity
}
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ if (DeviceUtils.isWear(this)) {
+ // Do not grab input focus and hide keyboard.
+ getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM);
+ }
int permissionsSdkLevel;
if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(getIntent().getAction())) {
@@ -231,8 +245,17 @@ public class GrantPermissionsActivity extends SettingsActivity
return;
}
- mRequestedPermissions = GrantPermissionsViewModel.Companion.getSanitizedPermissionsList(
- requestedPermissionsArray, permissionsSdkLevel);
+ boolean useNewViewModel = KotlinUtils.INSTANCE.isNewGrantDialogBackendEnabled();
+ if (useNewViewModel) {
+ mRequestedPermissions = removeNullOrEmptyPermissions(requestedPermissionsArray);
+ if (mIsSystemTriggered) {
+ mSystemRequestedPermissions.addAll(mRequestedPermissions);
+ }
+ } else {
+ mRequestedPermissions = GrantPermissionsViewModel.Companion
+ .getSanitizedPermissionsList(requestedPermissionsArray, permissionsSdkLevel);
+ }
+
if (mRequestedPermissions.isEmpty()) {
setResultAndFinish();
return;
@@ -277,10 +300,19 @@ public class GrantPermissionsActivity extends SettingsActivity
.GrantPermissionsViewHandlerImpl(this, this);
}
- GrantPermissionsViewModelFactory factory = new GrantPermissionsViewModelFactory(
- getApplication(), mTargetPackage, mRequestedPermissions, mSessionId, icicle);
if (!mDelegated) {
- mViewModel = factory.create(GrantPermissionsViewModel.class);
+ if (useNewViewModel) {
+ NewGrantPermissionsViewModelFactory factory =
+ new NewGrantPermissionsViewModelFactory(getApplication(), mTargetPackage,
+ mRequestedPermissions, mSystemRequestedPermissions, mSessionId,
+ icicle);
+ mViewModel = factory.create(NewGrantPermissionsViewModel.class);
+ } else {
+ GrantPermissionsViewModelFactory factory = new GrantPermissionsViewModelFactory(
+ getApplication(), mTargetPackage, mRequestedPermissions, mSessionId,
+ icicle);
+ mViewModel = factory.create(GrantPermissionsViewModel.class);
+ }
mViewModel.getRequestInfosLiveData().observe(this, this::onRequestInfoLoad);
}
@@ -364,10 +396,17 @@ public class GrantPermissionsActivity extends SettingsActivity
Bundle oldState = new Bundle();
mViewModel.getRequestInfosLiveData().removeObservers(this);
mViewModel.saveInstanceState(oldState);
- GrantPermissionsViewModelFactory factory = new GrantPermissionsViewModelFactory(
- getApplication(), mTargetPackage, mRequestedPermissions,
- mSessionId, oldState);
- mViewModel = factory.create(GrantPermissionsViewModel.class);
+ if (KotlinUtils.INSTANCE.isNewGrantDialogBackendEnabled()) {
+ NewGrantPermissionsViewModelFactory factory = new NewGrantPermissionsViewModelFactory(
+ getApplication(), mTargetPackage, mRequestedPermissions,
+ mSystemRequestedPermissions, mSessionId, oldState);
+ mViewModel = factory.create(GrantPermissionsViewModel.class);
+ } else {
+ GrantPermissionsViewModelFactory factory = new GrantPermissionsViewModelFactory(
+ getApplication(), mTargetPackage, mRequestedPermissions,
+ mSessionId, oldState);
+ mViewModel = factory.create(GrantPermissionsViewModel.class);
+ }
mViewModel.getRequestInfosLiveData().observe(this, this::onRequestInfoLoad);
if (follower != null) {
follower.mViewModel = mViewModel;
@@ -420,6 +459,13 @@ public class GrantPermissionsActivity extends SettingsActivity
} else if (info.getOpenPhotoPicker()) {
mViewModel.openPhotoPicker(top, GRANTED_USER_SELECTED);
return;
+ } else if (!info.getFilteredPermissions().isEmpty()) {
+ // Filtered permissions should be removed from the requested permissions list entirely,
+ // and not have status returned to the app
+ mRequestedPermissions.removeAll(info.getFilteredPermissions());
+ mRequestInfos.remove(info);
+ onRequestInfoLoad(mRequestInfos);
+ return;
}
if (Utils.isHealthPermissionUiEnabled() && HEALTH_PERMISSION_GROUP.equals(
@@ -428,26 +474,27 @@ public class GrantPermissionsActivity extends SettingsActivity
return;
}
- CharSequence appLabel = KotlinUtils.INSTANCE.getPackageLabel(getApplication(),
+ String appLabel = KotlinUtils.INSTANCE.getPackageLabel(getApplication(),
mTargetPackage, Process.myUserHandle());
Icon icon = null;
+ int deviceId = ContextCompat.getDeviceId(this);
int messageId = 0;
- switch(info.getMessage()) {
+ switch (info.getMessage()) {
case FG_MESSAGE:
- messageId = Utils.getRequest(info.getGroupName());
+ messageId = Utils.getRequest(info.getGroupName(), deviceId);
break;
case FG_FINE_LOCATION_MESSAGE:
- messageId = R.string.permgrouprequest_fineupgrade;
+ messageId = Utils.getFineLocationRequest(deviceId);
break;
case FG_COARSE_LOCATION_MESSAGE:
- messageId = R.string.permgrouprequest_coarselocation;
+ messageId = Utils.getCoarseLocationRequest(deviceId);
break;
case BG_MESSAGE:
- messageId = Utils.getBackgroundRequest(info.getGroupName());
+ messageId = Utils.getBackgroundRequest(info.getGroupName(), deviceId);
break;
case UPGRADE_MESSAGE:
- messageId = Utils.getUpgradeRequest(info.getGroupName());
+ messageId = Utils.getUpgradeRequest(info.getGroupName(), deviceId);
break;
case STORAGE_SUPERGROUP_MESSAGE_Q_TO_S:
icon = Icon.createWithResource(getPackageName(), mStoragePermGroupIcon);
@@ -458,15 +505,17 @@ public class GrantPermissionsActivity extends SettingsActivity
messageId = R.string.permgrouprequest_storage_pre_q;
break;
case MORE_PHOTOS_MESSAGE:
- messageId = R.string.permgrouprequest_more_photos;
+ messageId = Utils.getMorePhotosRequest(deviceId);
break;
+ default:
+ Log.w(LOG_TAG, "Unhandled message type: " + info.getMessage());
}
- CharSequence message = getRequestMessage(appLabel, mTargetPackage,
- info.getGroupName(), this, messageId);
+ CharSequence message = getRequestMessage(appLabel, mTargetPackage, info.getGroupName(),
+ getDeviceName(info.getDeviceId()), this, deviceId, messageId);
int detailMessageId = 0;
- switch(info.getDetailMessage()) {
+ switch (info.getDetailMessage()) {
case FG_MESSAGE:
detailMessageId = Utils.getRequestDetail(info.getGroupName());
break;
@@ -475,6 +524,9 @@ public class GrantPermissionsActivity extends SettingsActivity
break;
case UPGRADE_MESSAGE:
detailMessageId = Utils.getUpgradeRequestDetail(info.getGroupName());
+ break;
+ default:
+ Log.w(LOG_TAG, "Unhandled detail message type: " + info.getDetailMessage());
}
Spanned detailMessage = null;
@@ -507,8 +559,6 @@ public class GrantPermissionsActivity extends SettingsActivity
Log.e(LOG_TAG, "Cannot load icon for group" + info.getGroupName(), e);
}
- boolean showingNewGroup = message == null || !message.equals(getTitle());
-
// Set the permission message as the title so it can be announced. Skip on Wear
// because the dialog title is already announced, as is the default selection which
// is a text view containing the title.
@@ -542,21 +592,43 @@ public class GrantPermissionsActivity extends SettingsActivity
mRequestCounts = mRequestInfos.size();
}
- mViewHandler.updateUi(info.getGroupName(), mRequestCounts, mCurrentRequestIdx, icon,
+ int pageIdx = mRequestCounts - mRequestInfos.size();
+ mViewHandler.updateUi(info.getGroupName(), mRequestCounts, pageIdx, icon,
message, detailMessage, permissionRationaleMessage, mButtonVisibilities,
locationVisibilities);
- if (showingNewGroup) {
- mCurrentRequestIdx++;
- }
getWindow().setDimAmount(mOriginalDimAmount);
if (mRootView.getVisibility() == View.GONE) {
- InputMethodManager manager = getSystemService(InputMethodManager.class);
- manager.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
+ if (mIsSystemTriggered) {
+ // We don't want the keyboard obscuring system-triggered dialogs
+ InputMethodManager manager = getSystemService(InputMethodManager.class);
+ manager.hideSoftInputFromWindow(mRootView.getWindowToken(), 0);
+ }
mRootView.setVisibility(View.VISIBLE);
}
}
+ private String getDeviceName(int deviceId) {
+ // Pre Android V no permission requests can affect the VirtualDevice, thus return local
+ // device name.
+ if (!SdkLevel.isAtLeastV() || deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return Settings.Global.getString(getContentResolver(), Settings.Global.DEVICE_NAME);
+ }
+
+ VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
+ if (vdm != null) {
+ // TODO(b/298621125): replace with vdm.getVirtualDeviceById(deviceId) once the API is
+ // rolled out.
+ for (VirtualDevice virtualDevice : vdm.getVirtualDevices()) {
+ if (virtualDevice.getDeviceId() == deviceId) {
+ return virtualDevice.getDisplayName().toString();
+ }
+ }
+ }
+
+ throw new IllegalArgumentException("No device name for device: " + deviceId);
+ }
+
// LINT.IfChange(dispatchTouchEvent)
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
@@ -646,7 +718,6 @@ public class GrantPermissionsActivity extends SettingsActivity
logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result);
mViewModel.onPermissionGrantResult(name, affectedForegroundPermissions, result);
- showNextRequest();
if (result == CANCELED) {
setResultAndFinish();
}
@@ -877,6 +948,18 @@ public class GrantPermissionsActivity extends SettingsActivity
return mResultCode != Integer.MAX_VALUE;
}
+ // Remove null and empty permissions from an array, return a list
+ private List<String> removeNullOrEmptyPermissions(String[] perms) {
+ ArrayList<String> sanitized = new ArrayList<>();
+ for (String perm : perms) {
+ if (perm == null || perm.isEmpty()) {
+ continue;
+ }
+ sanitized.add(perm);
+ }
+ return sanitized;
+ }
+
/**
* If there is another system-shown dialog on another task, that is not being relied upon by an
* app-defined dialogs, these other dialogs should be finished.
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/ManagePermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/ManagePermissionsActivity.java
index afeb19aa9..53b024076 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/ManagePermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/ManagePermissionsActivity.java
@@ -31,7 +31,7 @@ import static com.android.permissioncontroller.PermissionControllerStatsLog.PERM
import static com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_USAGE_FRAGMENT_INTERACTION__ACTION__OPEN;
import android.Manifest;
-import android.app.ActionBar;
+import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -71,14 +71,14 @@ import com.android.permissioncontroller.permission.ui.auto.dashboard.AutoPermiss
import com.android.permissioncontroller.permission.ui.auto.dashboard.AutoPermissionUsageFragment;
import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment;
import com.android.permissioncontroller.permission.ui.handheld.AppPermissionGroupsFragment;
-import com.android.permissioncontroller.permission.ui.handheld.HandheldUnusedAppsWrapperFragment;
import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment;
import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionDetailsWrapperFragment;
import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionUsageWrapperFragment;
import com.android.permissioncontroller.permission.ui.handheld.v34.AppDataSharingUpdatesFragment;
import com.android.permissioncontroller.permission.ui.legacy.AppPermissionActivity;
import com.android.permissioncontroller.permission.ui.television.TvUnusedAppsFragment;
-import com.android.permissioncontroller.permission.ui.wear.AppPermissionsFragmentWear;
+import com.android.permissioncontroller.permission.ui.wear.WearAppPermissionFragment;
+import com.android.permissioncontroller.permission.ui.wear.WearUnusedAppsFragment;
import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.PermissionMapping;
import com.android.permissioncontroller.permission.utils.Utils;
@@ -138,11 +138,12 @@ public final class ManagePermissionsActivity extends SettingsActivity {
*/
private static final int PROXY_ACTIVITY_REQUEST_CODE = 5;
+ @TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
private static final String LAUNCH_PERMISSION_SETTINGS =
- "android.permission.LAUNCH_PERMISSION_SETTINGS";
+ Manifest.permission.LAUNCH_PERMISSION_SETTINGS;
- private static final String APP_PERMISSIONS_SETTINGS =
- "android.settings.APP_PERMISSIONS_SETTINGS";
+ @TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ private static final String APP_PERMISSIONS_SETTINGS = Settings.ACTION_APP_PERMISSIONS_SETTINGS;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -153,10 +154,10 @@ public final class ManagePermissionsActivity extends SettingsActivity {
}
super.onCreate(savedInstanceState);
- // If this is not a phone (which uses the Navigation component), and there is a previous
- // instance, re-use its Fragment instead of making a new one.
- if ((DeviceUtils.isTelevision(this) || DeviceUtils.isAuto(this)
- || DeviceUtils.isWear(this)) && savedInstanceState != null) {
+ // If this is not a phone or a watch (which uses the Navigation component), and there
+ // is a previous instance, re-use its Fragment instead of making a new one.
+ if ((DeviceUtils.isTelevision(this) || DeviceUtils.isAuto(this))
+ && savedInstanceState != null) {
return;
}
@@ -258,8 +259,7 @@ public final class ManagePermissionsActivity extends SettingsActivity {
}
case Intent.ACTION_MANAGE_APP_PERMISSION: {
- if (DeviceUtils.isAuto(this) || DeviceUtils.isTelevision(this)
- || DeviceUtils.isWear(this)) {
+ if (DeviceUtils.isAuto(this) || DeviceUtils.isTelevision(this)) {
Intent compatIntent = new Intent(this, AppPermissionActivity.class);
compatIntent.putExtras(getIntent().getExtras());
startActivityForResult(compatIntent, PROXY_ACTIVITY_REQUEST_CODE);
@@ -297,15 +297,22 @@ public final class ManagePermissionsActivity extends SettingsActivity {
return;
}
- Bundle args = AppPermissionFragment.createArgs(packageName, permissionName,
- groupName, userHandle, caller, sessionId, null);
+ Bundle args;
+ if (DeviceUtils.isWear(this)) {
+ args = WearAppPermissionFragment.createArgs(packageName, permissionName,
+ groupName, userHandle, caller, sessionId, null);
+ } else {
+ args = AppPermissionFragment.createArgs(packageName, permissionName,
+ groupName, userHandle, caller, sessionId, null);
+ }
setNavGraph(args, R.id.app_permission);
return;
}
case Intent.ACTION_MANAGE_APP_PERMISSIONS:
case APP_PERMISSIONS_SETTINGS: {
- if (Objects.equals(action, APP_PERMISSIONS_SETTINGS)) {
+ if (!SdkLevel.isAtLeastV()
+ && Objects.equals(action, APP_PERMISSIONS_SETTINGS)) {
PermissionInfo permissionInfo;
try {
permissionInfo = getPackageManager()
@@ -374,8 +381,6 @@ public final class ManagePermissionsActivity extends SettingsActivity {
androidXFragment = AutoAppPermissionsFragment.newInstance(packageName,
userHandle, sessionId, /* isSystemPermsScreen= */ true);
}
- } else if (DeviceUtils.isWear(this)) {
- androidXFragment = AppPermissionsFragmentWear.newInstance(packageName);
} else if (DeviceUtils.isTelevision(this)) {
androidXFragment = com.android.permissioncontroller.permission.ui.television
.AppPermissionsFragment.newInstance(packageName, userHandle);
@@ -473,8 +478,8 @@ public final class ManagePermissionsActivity extends SettingsActivity {
androidXFragment = TvUnusedAppsFragment.newInstance();
androidXFragment.setArguments(UnusedAppsFragment.createArgs(sessionId));
} else if (DeviceUtils.isWear(this)) {
- androidXFragment = HandheldUnusedAppsWrapperFragment.newInstance();
- androidXFragment.setArguments(UnusedAppsFragment.createArgs(sessionId));
+ setNavGraph(WearUnusedAppsFragment.createArgs(sessionId), R.id.auto_revoke);
+ return;
} else {
setNavGraph(UnusedAppsFragment.createArgs(sessionId), R.id.auto_revoke);
return;
@@ -549,15 +554,6 @@ public final class ManagePermissionsActivity extends SettingsActivity {
}
@Override
- public ActionBar getActionBar() {
- ActionBar ab = super.getActionBar();
- if (ab != null) {
- ab.setHomeActionContentDescription(R.string.back);
- }
- return ab;
- }
-
- @Override
public boolean onOptionsItemSelected(MenuItem item) {
// in automotive mode, there's no system wide back button, so need to add that
if (DeviceUtils.isAuto(this)) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/ui/TEST_MAPPING
index de4c3a2b9..2a4953f51 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/TEST_MAPPING
@@ -5,6 +5,9 @@
"options": [
{
"include-filter": "android.permission.cts.OneTimePermissionTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
@@ -17,14 +20,22 @@
"include-annotation": "com.android.cts.devicepolicy.annotations.PermissionsTest"
},
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
],
"postsubmit": [
{
- "name": "CtsPermission3TestCases"
+ "name": "CtsPermissionUiTestCases"
+ },
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.OneTimePermissionTest"
+ }
+ ]
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
index cf58f1e17..446d97c3e 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionsFragment.java
@@ -400,7 +400,7 @@ public class AutoAppPermissionsFragment extends AutoSettingsFrameFragment implem
}
PermissionControllerStatsLog.write(APP_PERMISSIONS_FRAGMENT_VIEWED, sessionId, viewId,
permissionGroupName, uid, mPackageName, category);
- Log.v(LOG_TAG, "AutoAppPermissionFragment view logged with sessionId=" + sessionId
+ Log.i(LOG_TAG, "AutoAppPermissionFragment view logged with sessionId=" + sessionId
+ " viewId=" + viewId + " permissionGroupName=" + permissionGroupName + " uid="
+ uid + " packageName="
+ mPackageName + " category=" + category);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
index 29fcb43b2..3b8419bcf 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoPermissionAppsFragment.java
@@ -22,6 +22,7 @@ import static com.android.permissioncontroller.permission.ui.Category.ALLOWED;
import static com.android.permissioncontroller.permission.ui.Category.ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.permission.ui.Category.ASK;
import static com.android.permissioncontroller.permission.ui.Category.DENIED;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_CALLER_NAME;
import android.content.Context;
@@ -52,15 +53,15 @@ import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.settingslib.utils.applications.AppUtils;
+import kotlin.Pair;
+import kotlin.Triple;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
-import kotlin.Pair;
-import kotlin.Triple;
-
/** Shows the list of applications which have (or do not have) the given permission. */
public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implements
PermissionUsages.PermissionsUsagesChangeCallback {
@@ -172,6 +173,10 @@ public class AutoPermissionAppsFragment extends AutoSettingsFrameFragment implem
}
// Hide allowed foreground label by default, to avoid briefly showing it before updating
findPreference(ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
+
+ // Hide storage footer category
+ findPreference(STORAGE_FOOTER.getCategoryName()).setVisible(false);
+
Context context = getPreferenceManager().getContext();
if (context == null || getActivity() == null || categories == null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/GrantPermissionsAutoViewHandler.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/GrantPermissionsAutoViewHandler.java
index 6b09921cb..5a93a8e76 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/GrantPermissionsAutoViewHandler.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/GrantPermissionsAutoViewHandler.java
@@ -102,7 +102,7 @@ public class GrantPermissionsAutoViewHandler implements GrantPermissionsViewHand
mGroupIcon = icon;
mGroupMessage = message;
mDetailMessage = detailMessage;
- mButtonVisibilities = buttonVisibilities;
+ setButtonVisibilities(buttonVisibilities);
update();
}
@@ -193,11 +193,19 @@ public class GrantPermissionsAutoViewHandler implements GrantPermissionsViewHand
mGroupCount = savedInstanceState.getInt(ARG_GROUP_COUNT);
mGroupIndex = savedInstanceState.getInt(ARG_GROUP_INDEX);
mDetailMessage = savedInstanceState.getCharSequence(ARG_GROUP_DETAIL_MESSAGE);
- mButtonVisibilities = savedInstanceState.getBooleanArray(ARG_BUTTON_VISIBILITIES);
+ setButtonVisibilities(savedInstanceState.getBooleanArray(ARG_BUTTON_VISIBILITIES));
update();
}
+ private void setButtonVisibilities(boolean[] visibilities) {
+ // If GrantPermissionsActivity sent the user directly to settings, button visibilities are
+ // not created. If the activity was then destroyed by the system, once the activity is
+ // recreated to perform onActivityResult, it will try to loadInstanceState in onCreate but
+ // the button visibilities were never set, so they will be null.
+ mButtonVisibilities = visibilities == null ? new boolean[0] : visibilities;
+ }
+
@Override
public void onBackPressed() {
if (mDialog != null) {
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 a8b79bfde..4bc14ed24 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -23,6 +23,7 @@ import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSIONS_FRAGMENT_VIEWED__CATEGORY__DENIED;
import static com.android.permissioncontroller.hibernation.HibernationPolicyKt.isHibernationEnabled;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.handheld.UtilsKt.pressBack;
import static java.util.concurrent.TimeUnit.DAYS;
@@ -318,6 +319,9 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
findPreference(Category.ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
+ // Hide storage footer category
+ findPreference(STORAGE_FOOTER.getCategoryName()).setVisible(false);
+
long sessionId = getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID);
for (Category grantCategory : groupMap.keySet()) {
@@ -580,7 +584,7 @@ public final class AppPermissionGroupsFragment extends SettingsWithLargeHeader i
}
PermissionControllerStatsLog.write(APP_PERMISSIONS_FRAGMENT_VIEWED, sessionId, viewId,
permissionGroupName, uid, mPackageName, category);
- Log.v(LOG_TAG, "AppPermissionFragment view logged with sessionId=" + sessionId + " viewId="
+ Log.i(LOG_TAG, "AppPermissionFragment view logged with sessionId=" + sessionId + " viewId="
+ viewId + " permissionGroupName=" + permissionGroupName + " uid="
+ uid + " packageName="
+ mPackageName + " category=" + category);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
index 8e3192eee..86fcf2c27 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
@@ -22,11 +22,8 @@ import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
import static com.android.permissioncontroller.permission.ui.handheld.UtilsKt.pressBack;
import android.app.Application;
-import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.lifecycle.ViewModelProvider;
@@ -35,10 +32,8 @@ import androidx.preference.PreferenceScreen;
import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
-import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity;
import com.android.permissioncontroller.permission.ui.UnusedAppsFragment;
import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel;
-import com.android.permissioncontroller.permission.utils.KotlinUtils;
import com.android.permissioncontroller.permission.utils.StringUtils;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.settingslib.widget.FooterPreference;
@@ -50,9 +45,6 @@ public final class ManageStandardPermissionsFragment extends ManagePermissionsFr
private static final String EXTRA_PREFS_KEY = "extra_prefs_key";
private static final String AUTO_REVOKE_KEY = "auto_revoke_key";
private static final String LOG_TAG = ManageStandardPermissionsFragment.class.getSimpleName();
-
- private static final int MENU_PERMISSION_USAGE = MENU_HIDE_SYSTEM + 1;
-
private ManageStandardPermissionsViewModel mViewModel;
/**
@@ -111,24 +103,11 @@ public final class ManageStandardPermissionsFragment extends ManagePermissionsFr
case android.R.id.home:
pressBack(this);
return true;
- case MENU_PERMISSION_USAGE:
- getActivity().startActivity(new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
- .setClass(getContext(), ManagePermissionsActivity.class));
- return true;
}
return super.onOptionsItemSelected(item);
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
-
- if (KotlinUtils.INSTANCE.shouldShowPermissionsDashboard()) {
- menu.add(Menu.NONE, MENU_PERMISSION_USAGE, Menu.NONE, R.string.permission_usage_title);
- }
- }
-
- @Override
protected PreferenceScreen updatePermissionsUi() {
PreferenceScreen screen = super.updatePermissionsUi();
if (screen == null) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
index 220507426..20dc50130 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -21,6 +21,7 @@ import static com.android.permissioncontroller.permission.ui.Category.ALLOWED;
import static com.android.permissioncontroller.permission.ui.Category.ALLOWED_FOREGROUND;
import static com.android.permissioncontroller.permission.ui.Category.ASK;
import static com.android.permissioncontroller.permission.ui.Category.DENIED;
+import static com.android.permissioncontroller.permission.ui.Category.STORAGE_FOOTER;
import static com.android.permissioncontroller.permission.ui.handheld.UtilsKt.pressBack;
import android.Manifest;
@@ -34,6 +35,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.safetycenter.SafetyCenterManager;
import android.util.ArrayMap;
import android.view.Menu;
import android.view.MenuInflater;
@@ -52,7 +54,6 @@ import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.v31.AppPermissionUsage;
import com.android.permissioncontroller.permission.model.v31.PermissionUsages;
import com.android.permissioncontroller.permission.ui.Category;
-import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity;
import com.android.permissioncontroller.permission.ui.handheld.v31.CardViewPreference;
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel;
import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory;
@@ -62,15 +63,15 @@ import com.android.settingslib.HelpUtils;
import com.android.settingslib.utils.applications.AppUtils;
import com.android.settingslib.widget.FooterPreference;
+import kotlin.Pair;
+import kotlin.Triple;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
-import kotlin.Pair;
-import kotlin.Triple;
-
/**
* Show and manage apps which request a single permission group.
*
@@ -87,11 +88,10 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private static final String STORAGE_ALLOWED_FULL = "allowed_storage_full";
private static final String STORAGE_ALLOWED_SCOPED = "allowed_storage_scoped";
private static final String BLOCKED_SENSOR_PREF_KEY = "sensor_card";
- private static final String STORAGE_FOOTER_CATEGORY_KEY = "storage_footer_category";
private static final String STORAGE_FOOTER_PREFERENCE_KEY = "storage_footer_preference";
private static final int SHOW_LOAD_DELAY_MS = 200;
- private static final int MENU_PERMISSION_USAGE = MENU_HIDE_SYSTEM + 1;
+ private static final String PRIVACY_CONTROLS_ACTION = "android.settings.PRIVACY_CONTROLS";
/**
* Create a bundle with the arguments needed by this fragment
@@ -197,10 +197,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
updateMenu(mViewModel.getShouldShowSystemLiveData().getValue());
}
- if (KotlinUtils.INSTANCE.shouldShowPermissionsDashboard()) {
- menu.add(Menu.NONE, MENU_PERMISSION_USAGE, Menu.NONE, R.string.permission_usage_title);
- }
-
if (!SdkLevel.isAtLeastS()) {
HelpUtils.prepareHelpMenuItem(getActivity(), menu, R.string.help_app_permissions,
getClass().getName());
@@ -218,11 +214,6 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
case MENU_HIDE_SYSTEM:
mViewModel.updateShowSystem(item.getItemId() == MENU_SHOW_SYSTEM);
break;
- case MENU_PERMISSION_USAGE:
- getActivity().startActivity(new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
- .setClass(getContext(), ManagePermissionsActivity.class)
- .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, mPermGroupName));
- return true;
}
return super.onOptionsItemSelected(item);
}
@@ -281,12 +272,31 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
findPreference(ALLOWED_FOREGROUND.getCategoryName()).setVisible(false);
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private String getPrivacyControlsIntent() {
+ Context context = getPreferenceManager().getContext();
+ SafetyCenterManager safetyCenterManager =
+ context.getSystemService(SafetyCenterManager.class);
+ if (safetyCenterManager.isSafetyCenterEnabled()) {
+ return PRIVACY_CONTROLS_ACTION;
+ } else {
+ return Settings.ACTION_PRIVACY_SETTINGS;
+ }
+ }
+
@RequiresApi(Build.VERSION_CODES.S)
private CardViewPreference createSensorCard() {
boolean isLocation = Manifest.permission_group.LOCATION.equals(mPermGroupName);
Context context = getPreferenceManager().getContext();
- String action = isLocation ? Settings.ACTION_LOCATION_SOURCE_SETTINGS
- : Settings.ACTION_PRIVACY_SETTINGS;
+
+ String action;
+ if (isLocation) {
+ action = Settings.ACTION_LOCATION_SOURCE_SETTINGS;
+ } else if (SdkLevel.isAtLeastT()) {
+ action = getPrivacyControlsIntent();
+ } else {
+ action = Settings.ACTION_PRIVACY_SETTINGS;
+ }
CardViewPreference sensorCard = new CardViewPreference(context, action);
sensorCard.setKey(BLOCKED_SENSOR_PREF_KEY);
sensorCard.setIcon(Utils.getBlockedIcon(mPermGroupName));
@@ -303,7 +313,7 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private void addStorageFooterSeeAllFilesAccess() {
PreferenceScreen screen = getPreferenceScreen();
Context context = screen.getPreferenceManager().getContext();
- PreferenceCategory preferenceCategory = findPreference(STORAGE_FOOTER_CATEGORY_KEY);
+ PreferenceCategory preferenceCategory = findPreference(STORAGE_FOOTER.getCategoryName());
Preference existingPreference = findPreference(STORAGE_FOOTER_PREFERENCE_KEY);
if (preferenceCategory == null || existingPreference != null) {
@@ -502,6 +512,13 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
if (SdkLevel.isAtLeastT() && Manifest.permission_group.STORAGE.equals(mPermGroupName)) {
addStorageFooterSeeAllFilesAccess();
+ } else {
+ // Hide storage footer category
+ PreferenceCategory storageFooterPreferenceCategory =
+ findPreference(STORAGE_FOOTER.getCategoryName());
+ if (storageFooterPreferenceCategory != null) {
+ storageFooterPreferenceCategory.setVisible(false);
+ }
}
mViewModel.setCreationLogged(true);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ReviewPermissionsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ReviewPermissionsFragment.java
index 5e5c221ae..36d8cce76 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ReviewPermissionsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ReviewPermissionsFragment.java
@@ -258,7 +258,7 @@ public final class ReviewPermissionsFragment extends PreferenceFragmentCompat
changeId, mViewModel.getPackageInfo().applicationInfo.uid,
group.getPackageName(),
permission.getName(), permission.isGrantedIncludingAppOp());
- Log.v(LOG_TAG, "Permission grant via permission review changeId=" + changeId + " uid="
+ Log.i(LOG_TAG, "Permission grant via permission review changeId=" + changeId + " uid="
+ mViewModel.getPackageInfo().applicationInfo.uid + " packageName="
+ group.getPackageName() + " permission="
+ permission.getName() + " granted=" + permission.isGrantedIncludingAppOp());
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
index 88b5ebe87..d74e745d4 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFooterPreference.kt
@@ -22,10 +22,10 @@ import android.text.style.ClickableSpan
import android.util.AttributeSet
import android.view.View
import android.widget.TextView
+import androidx.core.text.method.LinkMovementMethodCompat
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.compat.LinkMovementMethodCompat
/** A preference for a footer with an icon and a link. */
class AppDataSharingUpdatesFooterPreference : Preference {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
index 2db9bc4b4..9ec0ceb47 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/AppDataSharingUpdatesFragment.kt
@@ -282,7 +282,7 @@ class AppDataSharingUpdatesFragment : PermissionsFrameFragment() {
sessionId,
numberOfAppUpdates
)
- Log.v(
+ Log.i(
LOG_TAG,
"AppDataSharingUpdatesFragment viewed with" +
" sessionId=$sessionId" +
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
index 3998ca141..6267ebad6 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v34/PermissionRationaleViewHandlerImpl.kt
@@ -33,8 +33,8 @@ import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.annotation.RequiresApi
+import androidx.core.text.method.LinkMovementMethodCompat
import com.android.permissioncontroller.R
-import com.android.permissioncontroller.permission.compat.LinkMovementMethodCompat
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleViewHandler
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleViewHandler.Result.Companion.CANCELLED
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
index d789f4e1e..226208041 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AllAppPermissionsViewModel.kt
@@ -81,6 +81,8 @@ class AllAppPermissionsViewModel(
.filter { filterGroup == null || it.key == filterGroup }
.filter { (it.key != Manifest.permission_group.STORAGE ||
Utils.shouldShowStorage(packageInfo)) }
+ .filter { (!Utils.isHealthPermissionGroup(it.key) ||
+ Utils.shouldShowHealthPermission(packageInfo, it.key))}
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
index 99b40d8a7..0e4cb6b8f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/AppPermissionViewModel.kt
@@ -20,6 +20,7 @@ package com.android.permissioncontroller.permission.ui.model
import android.Manifest
import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
import android.Manifest.permission_group.READ_MEDIA_VISUAL
import android.annotation.SuppressLint
import android.app.Activity
@@ -375,9 +376,8 @@ class AppPermissionViewModel(
val detailId = getIndividualPermissionDetailResId(group)
detailResIdLiveData.value = detailId.first to detailId.second
}
- } else if (KotlinUtils.isPhotoPickerPromptEnabled() &&
- group.permGroupName == READ_MEDIA_VISUAL &&
- group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU) {
+ } else if (shouldShowPhotoPickerPromptForApp(group) &&
+ group.permGroupName == READ_MEDIA_VISUAL) {
// Allow / Select Photos / Deny case
allowedState.isShown = true
deniedState.isShown = true
@@ -471,6 +471,19 @@ class AppPermissionViewModel(
}
}
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
+ private fun shouldShowPhotoPickerPromptForApp(group: LightAppPermGroup): Boolean {
+ if (!isPhotoPickerPromptEnabled() ||
+ group.packageInfo.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) {
+ return false
+ }
+ if (group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return true
+ }
+ val userSelectedPerm = group.permissions[READ_MEDIA_VISUAL_USER_SELECTED] ?: return false
+ return !userSelectedPerm.isImplicit
+ }
+
fun registerPhotoPickerResultIfNeeded(fragment: Fragment) {
if (permGroupName != READ_MEDIA_VISUAL) {
return
@@ -1139,7 +1152,7 @@ class AppPermissionViewModel(
PermissionControllerStatsLog.write(APP_PERMISSION_FRAGMENT_ACTION_REPORTED, sessionId,
changeId, uid, packageName, permission.permInfo.name,
permission.isGrantedIncludingAppOp, permission.flags, buttonPressed)
- Log.v(LOG_TAG, "Permission changed via UI with sessionId=$sessionId changeId=" +
+ Log.i(LOG_TAG, "Permission changed via UI with sessionId=$sessionId changeId=" +
"$changeId uid=$uid packageName=$packageName permission=" + permission.permInfo.name +
" isGranted=" + permission.isGrantedIncludingAppOp + " permissionFlags=" +
permission.flags + " buttonPressed=$buttonPressed")
@@ -1157,7 +1170,7 @@ class AppPermissionViewModel(
packageName,
permGroupName,
permissionRationaleShown)
- Log.v(
+ Log.i(
LOG_TAG,
"AppPermission fragment viewed with sessionId=$sessionId uid=$uid " +
"packageName=$packageName permGroupName=$permGroupName " +
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
index 0680ffcd2..87be1f20d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -43,7 +43,6 @@ import android.os.UserManager
import android.permission.PermissionManager
import android.provider.MediaStore
import android.util.Log
-import androidx.annotation.ChecksSdkIntAtLeast
import androidx.core.util.Consumer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
@@ -119,12 +118,14 @@ import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT
import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
+import com.android.permissioncontroller.permission.utils.ContextCompat
import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.getDefaultPrecision
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.grantForegroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.isLocationAccuracyEnabled
+import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptSupported
import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeBackgroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeForegroundRuntimePermissions
import com.android.permissioncontroller.permission.utils.PermissionMapping
@@ -144,7 +145,7 @@ import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
* @param sessionId: A long to identify this session
* @param storedState: Previous state, if this activity was stopped and is being recreated
*/
-class GrantPermissionsViewModel(
+open class GrantPermissionsViewModel(
private val app: Application,
private val packageName: String,
private val requestedPermissions: List<String>,
@@ -187,6 +188,8 @@ class GrantPermissionsViewModel(
* A class which represents a correctly requested permission group, and the buttons and messages
* which should be shown with it.
*/
+ // TODO: 284183336, once the old viewModel is gone, this should be replaced with a Prompt and
+ // DenyButton
data class RequestInfo(
val groupInfo: LightPermGroupInfo,
val buttonVisibilities: List<Boolean> = List(NEXT_BUTTON) { false },
@@ -195,16 +198,19 @@ class GrantPermissionsViewModel(
val detailMessage: RequestMessage = RequestMessage.NO_MESSAGE,
val sendToSettingsImmediately: Boolean = false,
val openPhotoPicker: Boolean = false,
+ // Unused for now, will be included in the GrantPermissions refactor
+ val filteredPermissions: Collection<String> = emptyList(),
+ val deviceId: Int = ContextCompat.DEVICE_ID_DEFAULT,
) {
val groupName = groupInfo.name
}
- var activityResultCallback: Consumer<Intent>? = null
+ open var activityResultCallback: Consumer<Intent>? = null
/**
* A LiveData which holds a list of the currently pending RequestInfos
*/
- val requestInfosLiveData = object :
+ open val requestInfosLiveData = object :
SmartUpdateMediatorLiveData<List<RequestInfo>>() {
private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
private val packagePermissionsLiveData = PackagePermissionsLiveData[packageName, user]
@@ -261,7 +267,6 @@ class GrantPermissionsViewModel(
}
private fun setAppPermGroupsLiveDatas(groups: Map<String, List<String>>) {
-
val requestedGroups = groups.filter { (_, perms) ->
perms.any { it in unfilteredAffectedPermissions }
}
@@ -516,8 +521,8 @@ class GrantPermissionsViewModel(
// Show location permission dialogs based on location permissions
val locationVisibilities = MutableList(NEXT_LOCATION_DIALOG) { false }
- if (groupState.group.permGroupName == LOCATION && isLocationAccuracyEnabled() &&
- packageInfo.targetSdkVersion >= Build.VERSION_CODES.S) {
+ if (groupState.group.permGroupName == LOCATION &&
+ isLocationAccuracyEnabledForApp(groupState.group)) {
if (needFgPermissions) {
locationVisibilities[LOCATION_ACCURACY_LAYOUT] = true
if (fgState != null &&
@@ -619,7 +624,7 @@ class GrantPermissionsViewModel(
if (rhsHasOneTime && !lhsHasOneTime) {
-1
} else if ((!rhsHasOneTime && lhsHasOneTime) ||
- isHealthPermissionGroup(rhs.groupName)
+ Utils.isHealthPermissionGroup(rhs.groupName)
) {
1
} else {
@@ -709,7 +714,6 @@ class GrantPermissionsViewModel(
val splitPerms = app.getSystemService(PermissionManager::class.java)!!.splitPermissions
for (splitPerm in splitPerms) {
-
if (requestingAppTargetSDK < splitPerm.targetSdk && perm == splitPerm.splitPermission) {
extendedBySplitPerms.addAll(splitPerm.newPermissions)
}
@@ -738,7 +742,6 @@ class GrantPermissionsViewModel(
}
private fun isPermissionGrantableAndNotFixed(perm: String, group: LightAppPermGroup): Boolean {
-
// If the permission is restricted it does not show in the UI and
// is not added to the group at all, so check that first.
if (perm in group.packageInfo.requestedPermissions && perm !in group.permissions) {
@@ -764,7 +767,7 @@ class GrantPermissionsViewModel(
// Skip showing groups that we know cannot be granted.
return false
} else if (subGroup.isUserFixed) {
- if (perm == ACCESS_COARSE_LOCATION) {
+ if (perm == ACCESS_COARSE_LOCATION && isLocationAccuracyEnabledForApp(group)) {
val coarsePerm = group.permissions[perm]
if (coarsePerm != null && !coarsePerm.isUserFixed) {
// If the location group is user fixed but ACCESS_COARSE_LOCATION is not, then
@@ -868,7 +871,7 @@ class GrantPermissionsViewModel(
private fun canAutoGrantWholeGroup(group: LightAppPermGroup): Boolean {
// If FINE location is not granted, do not grant it automatically when COARSE
// location is already granted.
- if (group.permGroupName == LOCATION &&
+ if (group.permGroupName == LOCATION && isLocationAccuracyEnabledForApp(group) &&
group.allPermissions[ACCESS_FINE_LOCATION]?.isGrantedIncludingAppOp == false) {
return false
}
@@ -887,7 +890,7 @@ class GrantPermissionsViewModel(
* ACCESS_MEDIA_LOCATION granted
*/
private fun isPartialStorageGrant(group: LightAppPermGroup): Boolean {
- if (!KotlinUtils.isPhotoPickerPromptEnabled() || group.permGroupName != READ_MEDIA_VISUAL) {
+ if (!isPhotoPickerPromptSupported() || group.permGroupName != READ_MEDIA_VISUAL) {
return false
}
@@ -948,7 +951,7 @@ class GrantPermissionsViewModel(
* @param affectedForegroundPermissions The name of the foreground permission which was changed
* @param result The choice the user made regarding the group.
*/
- fun onPermissionGrantResult(
+ open fun onPermissionGrantResult(
groupName: String?,
affectedForegroundPermissions: List<String>?,
result: Int
@@ -1235,7 +1238,7 @@ class GrantPermissionsViewModel(
safetyLabelInfoLiveData?.value?.safetyLabel,
PermissionMapping.getGroupOfPlatformPermission(permission))
- Log.v(LOG_TAG, "Permission grant result requestId=$sessionId " +
+ Log.i(LOG_TAG, "Permission grant result requestId=$sessionId " +
"callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " +
"isImplicit=$isImplicit result=$result " +
"isPermissionRationaleShown=$isPermissionRationaleShown")
@@ -1252,7 +1255,7 @@ class GrantPermissionsViewModel(
*
* @param outState The bundle in which to store state
*/
- fun saveInstanceState(outState: Bundle) {
+ open fun saveInstanceState(outState: Bundle) {
for ((groupKey, groupState) in groupStates) {
val (groupName, isBackground) = groupKey
outState.putInt(getInstanceStateKey(groupName, isBackground), groupState.state)
@@ -1265,7 +1268,7 @@ class GrantPermissionsViewModel(
* @return Whether or not state should be returned. False only if the package is pre-M, true
* otherwise.
*/
- fun shouldReturnPermissionState(): Boolean {
+ open fun shouldReturnPermissionState(): Boolean {
return if (packageInfoLiveData.value != null) {
packageInfoLiveData.value!!.targetSdkVersion >= Build.VERSION_CODES.M
} else {
@@ -1280,12 +1283,7 @@ class GrantPermissionsViewModel(
}
}
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
- private fun isHealthPermissionGroup(permGroupName: String): Boolean {
- return SdkLevel.isAtLeastU() && HEALTH_PERMISSION_GROUP.equals(permGroupName)
- }
-
- fun handleHealthConnectPermissions(activity: Activity) {
+ open fun handleHealthConnectPermissions(activity: Activity) {
if (activityResultCallback == null) {
activityResultCallback = Consumer {
permGroupsToSkip.add(HEALTH_PERMISSION_GROUP)
@@ -1309,7 +1307,7 @@ class GrantPermissionsViewModel(
* @param activity The current activity
* @param groupName The name of the permission group whose fragment should be opened
*/
- fun sendDirectlyToSettings(activity: Activity, groupName: String) {
+ open fun sendDirectlyToSettings(activity: Activity, groupName: String) {
if (activityResultCallback == null) {
activityResultCallback = Consumer { data ->
if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) {
@@ -1333,7 +1331,7 @@ class GrantPermissionsViewModel(
}
}
- fun openPhotoPicker(activity: Activity, result: Int) {
+ open fun openPhotoPicker(activity: Activity, result: Int) {
if (activityResultCallback != null) {
return
}
@@ -1369,7 +1367,7 @@ class GrantPermissionsViewModel(
* @param activity The current activity
* @param groupName The name of the permission group whose fragment should be opened
*/
- fun sendToSettingsFromLink(activity: Activity, groupName: String) {
+ open fun sendToSettingsFromLink(activity: Activity, groupName: String) {
startAppPermissionFragment(activity, groupName)
activityResultCallback = Consumer { data ->
val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
@@ -1388,7 +1386,7 @@ class GrantPermissionsViewModel(
* @param activity The current activity
* @param groupName The name of the permission group whose fragment should be opened
*/
- fun showPermissionRationaleActivity(activity: Activity, groupName: String) {
+ open fun showPermissionRationaleActivity(activity: Activity, groupName: String) {
if (!SdkLevel.isAtLeastU()) {
return
}
@@ -1475,10 +1473,15 @@ class GrantPermissionsViewModel(
}
}
+ private fun isLocationAccuracyEnabledForApp(group: LightAppPermGroup): Boolean {
+ return isLocationAccuracyEnabled() &&
+ group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.S
+ }
+
/**
* Log all permission groups which were requested
*/
- fun logRequestedPermissionGroups() {
+ open fun logRequestedPermissionGroups() {
if (groupStates.isEmpty()) {
return
}
@@ -1495,7 +1498,7 @@ class GrantPermissionsViewModel(
* @param clickedButton The button that was clicked by the user
* @param presentedButtons All buttons which were shown to the user
*/
- fun logClickedButtons(
+ open fun logClickedButtons(
groupName: String?,
selectedPrecision: Int,
clickedButton: Int,
@@ -1516,21 +1519,21 @@ class GrantPermissionsViewModel(
}
PermissionControllerStatsLog.write(GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS,
- groupName, packageInfo.uid, packageName, presentedButtons, clickedButton, sessionId,
- packageInfo.targetSdkVersion, selectedPrecision,
- isPermissionRationaleShown)
- Log.v(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
- "$groupName uid=${packageInfo.uid} selectedPrecision=$selectedPrecision " +
- "package=$packageName presentedButtons=$presentedButtons " +
- "clickedButton=$clickedButton isPermissionRationaleShown=" +
- "$isPermissionRationaleShown sessionId=$sessionId " +
- "targetSdk=${packageInfo.targetSdkVersion}")
+ groupName, packageInfo.uid, packageName, presentedButtons, clickedButton, sessionId,
+ packageInfo.targetSdkVersion, selectedPrecision,
+ isPermissionRationaleShown)
+ Log.i(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
+ "$groupName uid=${packageInfo.uid} selectedPrecision=$selectedPrecision " +
+ "package=$packageName presentedButtons=$presentedButtons " +
+ "clickedButton=$clickedButton isPermissionRationaleShown=" +
+ "$isPermissionRationaleShown sessionId=$sessionId " +
+ "targetSdk=${packageInfo.targetSdkVersion}")
}
/**
* Use the autoGrantNotifier to notify of auto-granted permissions.
*/
- fun autoGrantNotify() {
+ open fun autoGrantNotify() {
autoGrantNotifier?.notifyOfAutoGrantPermissions(true)
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/NewGrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/NewGrantPermissionsViewModel.kt
new file mode 100644
index 000000000..50f22b7df
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/NewGrantPermissionsViewModel.kt
@@ -0,0 +1,1300 @@
+/*
+ * 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.
+ */
+@file:Suppress("DEPRECATION")
+
+package com.android.permissioncontroller.permission.ui.model
+
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+import android.Manifest.permission_group.LOCATION
+import android.Manifest.permission_group.NOTIFICATIONS
+import android.Manifest.permission_group.READ_MEDIA_AURAL
+import android.Manifest.permission_group.READ_MEDIA_VISUAL
+import android.Manifest.permission_group.STORAGE
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.Application
+import android.app.admin.DevicePolicyManager
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED
+import android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED
+import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
+import android.health.connect.HealthConnectManager.ACTION_REQUEST_HEALTH_PERMISSIONS
+import android.health.connect.HealthConnectManager.isHealthPermission
+import android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP
+import android.os.Build
+import android.os.Bundle
+import android.os.Process
+import android.permission.PermissionManager
+import android.provider.MediaStore
+import android.util.Log
+import androidx.core.util.Consumer
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.android.modules.utils.build.SdkLevel
+import com.android.permission.safetylabel.SafetyLabel
+import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.DeviceUtils
+import com.android.permissioncontroller.PermissionControllerStatsLog
+import com.android.permissioncontroller.PermissionControllerStatsLog.GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_DENIED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_POLICY_FIXED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_RESTRICTED_PERMISSION
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_USER_FIXED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__PHOTOS_SELECTED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE_IN_SETTINGS
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_ONE_TIME
+import com.android.permissioncontroller.PermissionControllerStatsLog.PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED
+import com.android.permissioncontroller.auto.DrivingDecisionReminderService
+import com.android.permissioncontroller.permission.data.LightAppPermGroupLiveData
+import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData
+import com.android.permissioncontroller.permission.data.PackagePermissionsLiveData
+import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
+import com.android.permissioncontroller.permission.data.get
+import com.android.permissioncontroller.permission.data.v34.SafetyLabelInfoLiveData
+import com.android.permissioncontroller.permission.model.AppPermissionGroup
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
+import com.android.permissioncontroller.permission.service.PermissionChangeStorageImpl
+import com.android.permissioncontroller.permission.service.v33.PermissionDecisionStorageImpl
+import com.android.permissioncontroller.permission.ui.AutoGrantPermissionsNotifier
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ALL_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_FOREGROUND_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ONE_TIME_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_SELECTED_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.COARSE_RADIO_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_BOTH_LOCATIONS
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_COARSE_LOCATION_ONLY
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_FINE_LOCATION_ONLY
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DONT_ALLOW_MORE_SELECTED_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.FINE_RADIO_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.INTENT_PHOTOS_SELECTED
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.LINK_TO_PERMISSION_RATIONALE
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.LOCATION_ACCURACY_LAYOUT
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NEXT_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NEXT_LOCATION_DIALOG
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.CANCELED
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_DO_NOT_ASK_AGAIN
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_MORE
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_ALWAYS
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_FOREGROUND_ONLY
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_ONE_TIME
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_USER_SELECTED
+import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
+import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED
+import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT
+import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.Companion.RequestMessage
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.BackgroundGrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.BasicGrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.GrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.HealthGrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.LocationGrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.NotificationGrantBehavior
+import com.android.permissioncontroller.permission.ui.model.grantPermissions.StorageGrantBehavior
+import com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity
+import com.android.permissioncontroller.permission.utils.ContextCompat
+import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.KotlinUtils.grantBackgroundRuntimePermissions
+import com.android.permissioncontroller.permission.utils.KotlinUtils.grantForegroundRuntimePermissions
+import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeBackgroundRuntimePermissions
+import com.android.permissioncontroller.permission.utils.KotlinUtils.revokeForegroundRuntimePermissions
+import com.android.permissioncontroller.permission.utils.PermissionMapping
+import com.android.permissioncontroller.permission.utils.PermissionMapping.getPartialStorageGrantPermissionsForGroup
+import com.android.permissioncontroller.permission.utils.SafetyNetLogger
+import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
+import com.android.permissioncontroller.permission.utils.v34.SafetyLabelUtils
+
+/**
+ * ViewModel for the GrantPermissionsActivity. Tracks all permission groups that are affected by
+ * the permissions requested by the user, and generates a RequestInfo object for each group, if
+ * action is needed. It will not return any data if one of the requests is malformed.
+ *
+ * @param app: The current application
+ * @param packageName: The packageName permissions are being requested for
+ * @param requestedPermissions: The list of permissions requested
+ * @param systemRequestedPermissions: The list of permissions requested as a result of a system
+ * triggered dialog, not an app-triggered dialog
+ * @param sessionId: A long to identify this session
+ * @param storedState: Previous state, if this activity was stopped and is being recreated
+ */
+class NewGrantPermissionsViewModel(
+ private val app: Application,
+ private val packageName: String,
+ private val requestedPermissions: List<String>,
+ private val systemRequestedPermissions: List<String>,
+ private val sessionId: Long,
+ private val storedState: Bundle?
+) : GrantPermissionsViewModel(app, packageName, requestedPermissions, sessionId, storedState) {
+ private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
+ private val user = Process.myUserHandle()
+ private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
+ private val safetyLabelInfoLiveData =
+ if (SdkLevel.isAtLeastU() && requestedPermissions
+ .mapNotNull { PermissionMapping.getGroupOfPlatformPermission(it) }
+ .any { PermissionMapping.isSafetyLabelAwarePermissionGroup(it) }) {
+ SafetyLabelInfoLiveData[packageName, user]
+ } else {
+ null
+ }
+ private val dpm = app.getSystemService(DevicePolicyManager::class.java)!!
+ private val permissionPolicy = dpm.getPermissionPolicy(null)
+ private val groupStates = mutableMapOf<String, GroupState>()
+
+ private var autoGrantNotifier: AutoGrantPermissionsNotifier? = null
+ private fun getAutoGrantNotifier(): AutoGrantPermissionsNotifier {
+ autoGrantNotifier = AutoGrantPermissionsNotifier(app, packageInfo.toPackageInfo(app)!!)
+ return autoGrantNotifier!!
+ }
+
+ private lateinit var packageInfo: LightPackageInfo
+
+ // All permissions that could possibly be affected by the provided requested permissions, before
+ // filtering system fixed, auto grant, etc.
+ private var unfilteredAffectedPermissions = requestedPermissions
+
+ private var appPermGroupLiveDatas = mutableMapOf<String, LightAppPermGroupLiveData>()
+
+ override var activityResultCallback: Consumer<Intent>? = null
+
+ /**
+ * An internal class which represents the state of a current AppPermissionGroup grant request.
+ * It is made up of the following:
+ * @param group The LightAppPermGroup representing the current state of the permissions for
+ * this app
+ * @param affectedPermissions The permissions that should be affected by this
+ */
+ internal class GroupState(
+ internal val group: LightAppPermGroup,
+ internal val affectedPermissions: MutableSet<String> = mutableSetOf(),
+ internal var state: Int = STATE_UNKNOWN,
+ ) {
+ val fgPermissions = affectedPermissions - group.backgroundPermNames.toSet()
+ val bgPermissions = affectedPermissions - fgPermissions
+
+ override fun toString(): String {
+ val stateStr: String = when (state) {
+ STATE_UNKNOWN -> "unknown"
+ STATE_GRANTED -> "granted"
+ STATE_DENIED -> "denied"
+ STATE_FG_GRANTED_BG_UNKNOWN -> "foreground granted, background unknown"
+ else -> "skipped"
+ }
+ return "${group.permGroupName} $stateStr $affectedPermissions"
+ }
+ }
+
+ /**
+ * A LiveData which holds a list of the currently pending RequestInfos
+ * TODO 284183336: Once the old ViewModel is gone, remove RequestInfo, and replace it with
+ * just a prompt + denyButton
+ */
+ override val requestInfosLiveData = object :
+ SmartUpdateMediatorLiveData<List<RequestInfo>>() {
+ private val LOG_TAG = GrantPermissionsViewModel::class.java.simpleName
+ private val packagePermissionsLiveData = PackagePermissionsLiveData[packageName, user]
+
+ init {
+ addSource(packagePermissionsLiveData) { onPackageLoaded() }
+ addSource(packageInfoLiveData) { onPackageLoaded() }
+ if (safetyLabelInfoLiveData != null) {
+ addSource(safetyLabelInfoLiveData) { onPackageLoaded() }
+ }
+
+ // Load package state, if available
+ onPackageLoaded()
+ }
+
+ private fun onPackageLoaded() {
+ if (packageInfoLiveData.isStale ||
+ packagePermissionsLiveData.isStale ||
+ (safetyLabelInfoLiveData != null && safetyLabelInfoLiveData.isStale)) {
+ return
+ }
+
+ val groups = packagePermissionsLiveData.value
+ val pI = packageInfoLiveData.value
+ if (groups.isNullOrEmpty() || pI == null) {
+ Log.e(LOG_TAG, "Package $packageName not found")
+ value = null
+ return
+ }
+ packageInfo = pI
+
+ if (packageInfo.requestedPermissions.isEmpty() ||
+ packageInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ Log.e(LOG_TAG, "Package $packageName has no requested permissions, or " +
+ "is a pre-M app")
+ value = null
+ return
+ }
+
+ val affectedPermissions = requestedPermissions.toMutableSet()
+ for (requestedPerm in requestedPermissions) {
+ affectedPermissions.addAll(getAffectedSplitPermissions(requestedPerm))
+ }
+ if (packageInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+ // For < O apps all permissions of the groups of the requested ones are affected
+ for (affectedPerm in affectedPermissions.toSet()) {
+ val otherGroupPerms =
+ groups.values.firstOrNull { affectedPerm in it } ?: emptyList()
+ affectedPermissions.addAll(otherGroupPerms)
+ }
+ }
+ unfilteredAffectedPermissions = affectedPermissions.toList()
+
+ setAppPermGroupsLiveDatas(groups.toMutableMap().apply {
+ remove(PackagePermissionsLiveData.NON_RUNTIME_NORMAL_PERMS)
+ })
+ }
+
+ private fun setAppPermGroupsLiveDatas(groups: Map<String, List<String>>) {
+ val requestedGroups = groups.filter { (_, perms) ->
+ perms.any { it in unfilteredAffectedPermissions }
+ }
+
+ if (requestedGroups.isEmpty()) {
+ Log.e(LOG_TAG, "None of " +
+ "$unfilteredAffectedPermissions in $groups")
+ value = null
+ return
+ }
+
+ val getLiveDataFun = { groupName: String ->
+ LightAppPermGroupLiveData[packageName, groupName, user]
+ }
+ setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun)
+ }
+
+ override fun onUpdate() {
+ if (appPermGroupLiveDatas.any { it.value.isStale }) {
+ return
+ }
+ var newGroups = false
+ for ((groupName, groupLiveData) in appPermGroupLiveDatas) {
+ val appPermGroup = groupLiveData.value
+ if (appPermGroup == null) {
+ Log.e(LOG_TAG, "Group $packageName $groupName invalid")
+ groupStates[groupName]?.state = STATE_SKIPPED
+ continue
+ }
+
+ packageInfo = appPermGroup.packageInfo
+
+ val state = groupStates[groupName]
+ if (state != null) {
+ val allAffectedGranted = state.affectedPermissions.all { perm ->
+ appPermGroup.permissions[perm]?.isGrantedIncludingAppOp == true &&
+ appPermGroup.permissions[perm]?.isRevokeWhenRequested == false
+ }
+ if (allAffectedGranted) {
+ groupStates[groupName]!!.state = STATE_GRANTED
+ }
+ } else {
+ newGroups = true
+ }
+ }
+
+ if (newGroups) {
+ addRequiredGroupStates(appPermGroupLiveDatas.mapNotNull { it.value.value })
+ }
+ setRequestInfosFromGroupStates()
+ }
+
+ private fun setRequestInfosFromGroupStates() {
+ val requestInfos = mutableListOf<RequestInfo>()
+ for (groupState in groupStates.values) {
+ if (!isStateUnknown(groupState.state)) {
+ continue
+ }
+ val behavior = getGrantBehavior(groupState.group)
+ val isSystemTriggered =
+ groupState.affectedPermissions.any { it in systemRequestedPermissions}
+ val prompt = behavior.getPrompt(groupState.group, groupState.affectedPermissions,
+ isSystemTriggered)
+ if (prompt == Prompt.NO_UI_REJECT_ALL_GROUPS) {
+ value = null
+ return
+ }
+ if (prompt == Prompt.NO_UI_REJECT_THIS_GROUP) {
+ reportRequestResult(groupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED)
+ continue
+ }
+
+ val denyBehavior = behavior.getDenyButton(groupState.group,
+ groupState.affectedPermissions, prompt)
+ requestInfos.add(convertPromptToRequestInfo(groupState, prompt, denyBehavior))
+ }
+ sortPermissionGroups(requestInfos)
+
+ value = if (requestInfos.any { it.sendToSettingsImmediately } &&
+ requestInfos.size > 1) {
+ Log.e(LOG_TAG, "For R+ apps, background permissions must be requested " +
+ "individually")
+ null
+ } else {
+ requestInfos
+ }
+ }
+ }
+
+ private fun shouldShowPermissionRationale(
+ safetyLabel: SafetyLabel?,
+ permissionGroupName: String?
+ ): Boolean {
+ if (safetyLabel == null || permissionGroupName == null) {
+ return false
+ }
+
+ val purposes = SafetyLabelUtils.getSafetyLabelSharingPurposesForGroup(safetyLabel,
+ permissionGroupName)
+ return purposes.isNotEmpty()
+ }
+
+ /**
+ * Converts a list of LightAppPermGroups into a list of GroupStates, and adds new GroupState
+ * objects to the tracked groupStates.
+ */
+ private fun addRequiredGroupStates(groups: List<LightAppPermGroup>) {
+ val filteredPermissions = unfilteredAffectedPermissions.filter { perm ->
+ val group = getGroupWithPerm(perm, groups)
+ group != null && isPermissionGrantableAndNotFixed(perm, group)
+ }
+ val newGroupStates = mutableMapOf<String, GroupState>()
+ for (perm in filteredPermissions) {
+ val group = getGroupWithPerm(perm, groups)!!
+
+ val oldGroupState = groupStates[group.permGroupName]
+ if (!isStateUnknown(oldGroupState?.state)) {
+ // we've already dealt with this group
+ continue
+ }
+
+ val groupState = newGroupStates.getOrPut(group.permGroupName) { GroupState(group) }
+
+ var currGroupState = groupState.state
+ if (storedState != null && !isStateUnknown(groupState.state)) {
+ currGroupState = storedState.getInt(group.permGroupName, STATE_UNKNOWN)
+ }
+
+ val otherAffectedPermissionsInGroup =
+ filteredPermissions.filter { it in group.permissions }.toSet()
+ val groupStateOfPerm = getGroupState(perm, group, otherAffectedPermissionsInGroup)
+ if (groupStateOfPerm != STATE_UNKNOWN) {
+ // update the state if it is allowed, denied, or granted in foreground
+ currGroupState = groupStateOfPerm
+ }
+
+ if (currGroupState != STATE_UNKNOWN) {
+ groupState.state = currGroupState
+ }
+
+ groupState.affectedPermissions.add(perm)
+ }
+ newGroupStates.forEach { (groupName, groupState) -> groupStates[groupName] = groupState }
+ }
+
+ /**
+ * Add additional permissions that should be granted in this request. For permissions that have
+ * split permissions, and apps that target an SDK before the split, this method automatically
+ * adds the split off permission.
+ *
+ * @param perm The requested permission
+ *
+ * @return The requested permissions plus any needed split permissions
+ */
+ private fun getAffectedSplitPermissions(
+ perm: String,
+ ): List<String> {
+ val requestingAppTargetSDK = packageInfo.targetSdkVersion
+
+ // If a permission is split, all permissions the original permission is split into are
+ // affected
+ val extendedBySplitPerms = mutableListOf(perm)
+
+ val splitPerms = app.getSystemService(PermissionManager::class.java)!!.splitPermissions
+ for (splitPerm in splitPerms) {
+ if (requestingAppTargetSDK < splitPerm.targetSdk && perm == splitPerm.splitPermission) {
+ extendedBySplitPerms.addAll(splitPerm.newPermissions)
+ }
+ }
+ return extendedBySplitPerms
+ }
+
+ private fun isPermissionGrantableAndNotFixed(perm: String, group: LightAppPermGroup): Boolean {
+ // If the permission is restricted it does not show in the UI and
+ // is not added to the group at all, so check that first.
+ if (perm in group.packageInfo.requestedPermissions && perm !in group.permissions) {
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_RESTRICTED_PERMISSION)
+ return false
+ }
+
+ val subGroup = if (perm in group.backgroundPermNames) {
+ group.background
+ } else {
+ group.foreground
+ }
+
+ val lightPermission = group.permissions[perm] ?: return false
+
+ if (!subGroup.isGrantable) {
+ reportRequestResult(perm, PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED)
+ // Skip showing groups that we know cannot be granted.
+ return false
+ }
+
+ if (subGroup.isPolicyFixed && !subGroup.isGranted || lightPermission.isPolicyFixed) {
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_POLICY_FIXED)
+ return false
+ }
+
+ val behavior = getGrantBehavior(group)
+ if (behavior.isPermissionFixed(group, perm)) {
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__IGNORED_USER_FIXED)
+ return false
+ }
+
+ return true
+ }
+
+ private fun getGroupState(
+ perm: String,
+ group: LightAppPermGroup,
+ groupRequestedPermissions: Set<String>
+ ): Int {
+ val policyState = getStateFromPolicy(perm, group)
+ if (!isStateUnknown(policyState)) {
+ return policyState
+ }
+
+ val isBackground = perm in group.backgroundPermNames
+
+ val behavior = getGrantBehavior(group)
+ return if (behavior.isGroupFullyGranted(group, groupRequestedPermissions)) {
+ if (group.permissions[perm]?.isGrantedIncludingAppOp == false) {
+ if (isBackground) {
+ grantBackgroundRuntimePermissions(app, group, listOf(perm))
+ } else {
+ grantForegroundRuntimePermissions(app, group, listOf(perm), group.isOneTime)
+ }
+ KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_SET to false,
+ FLAG_PERMISSION_USER_FIXED to false, filterPermissions = listOf(perm))
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED)
+ }
+ STATE_GRANTED
+ } else if (behavior.isForegroundFullyGranted(group, groupRequestedPermissions)) {
+ STATE_FG_GRANTED_BG_UNKNOWN
+ } else {
+ STATE_UNKNOWN
+ }
+ }
+
+ private fun getStateFromPolicy(perm: String, group: LightAppPermGroup): Int {
+ val isBackground = perm in group.backgroundPermNames
+ var state = STATE_UNKNOWN
+ when (permissionPolicy) {
+ DevicePolicyManager.PERMISSION_POLICY_AUTO_GRANT -> {
+ if (AdminRestrictedPermissionsUtils.mayAdminGrantPermission(
+ app, perm, user.identifier)) {
+ if (isBackground) {
+ grantBackgroundRuntimePermissions(app, group, listOf(perm))
+ } else {
+ grantForegroundRuntimePermissions(app, group, listOf(perm))
+ }
+ KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_POLICY_FIXED to true,
+ FLAG_PERMISSION_USER_SET to false, FLAG_PERMISSION_USER_FIXED to false,
+ filterPermissions = listOf(perm))
+ state = STATE_GRANTED
+ getAutoGrantNotifier().onPermissionAutoGranted(perm)
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_GRANTED)
+ }
+ }
+
+ DevicePolicyManager.PERMISSION_POLICY_AUTO_DENY -> {
+ if (group.permissions[perm]?.isPolicyFixed == false) {
+ KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_POLICY_FIXED to true,
+ FLAG_PERMISSION_USER_SET to false, FLAG_PERMISSION_USER_FIXED to false,
+ filterPermissions = listOf(perm))
+ }
+ state = STATE_DENIED
+ reportRequestResult(perm,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__AUTO_DENIED)
+ }
+ }
+ return state
+ }
+
+ /**
+ * Upon the user clicking a button, grant permissions, if applicable.
+ *
+ * @param groupName The name of the permission group which was changed
+ * @param affectedForegroundPermissions The name of the foreground permission which was changed
+ * @param result The choice the user made regarding the group.
+ */
+ override fun onPermissionGrantResult(
+ groupName: String?,
+ affectedForegroundPermissions: List<String>?,
+ result: Int
+ ) {
+ onPermissionGrantResult(groupName, affectedForegroundPermissions, result, false)
+ }
+
+ private fun onPermissionGrantResult(
+ groupName: String?,
+ affectedForegroundPermissions: List<String>?,
+ result: Int,
+ alreadyRequestedStorageGroupsIfNeeded: Boolean
+ ) {
+ if (groupName == null) {
+ return
+ }
+
+ // If this is a legacy app, and a storage group is requested: request all storage groups
+ if (!alreadyRequestedStorageGroupsIfNeeded &&
+ groupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS &&
+ packageInfo.targetSdkVersion <= Build.VERSION_CODES.S_V2) {
+ for (storageGroupName in PermissionMapping.STORAGE_SUPERGROUP_PERMISSIONS) {
+ val groupPerms = appPermGroupLiveDatas[storageGroupName]
+ ?.value?.allPermissions?.keys?.toList()
+ onPermissionGrantResult(storageGroupName, groupPerms, result, true)
+ }
+ return
+ }
+
+ val groupState = groupStates[groupName] ?: return
+ when (result) {
+ CANCELED -> {
+ reportRequestResult(groupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_IGNORED)
+ groupState.state = STATE_SKIPPED
+ requestInfosLiveData.update()
+ return
+ }
+ GRANTED_ALWAYS -> {
+ onPermissionGrantResultSingleState(groupState,
+ affectedForegroundPermissions, granted = true, isOneTime = false,
+ foregroundOnly = false, doNotAskAgain = false)
+ }
+ GRANTED_FOREGROUND_ONLY -> {
+ onPermissionGrantResultSingleState(groupState,
+ affectedForegroundPermissions, granted = true, isOneTime = false,
+ foregroundOnly = true, doNotAskAgain = false)
+ }
+ GRANTED_ONE_TIME -> {
+ onPermissionGrantResultSingleState(groupState,
+ affectedForegroundPermissions, granted = true, isOneTime = true,
+ foregroundOnly = false, doNotAskAgain = false)
+ }
+ GRANTED_USER_SELECTED, DENIED_MORE -> {
+ grantUserSelectedVisualGroupPermissions(groupState)
+ }
+ DENIED -> {
+ onPermissionGrantResultSingleState(groupState,
+ affectedForegroundPermissions, granted = false, isOneTime = false,
+ foregroundOnly = false, doNotAskAgain = false)
+ }
+ DENIED_DO_NOT_ASK_AGAIN -> {
+ onPermissionGrantResultSingleState(groupState,
+ affectedForegroundPermissions, granted = false, isOneTime = false,
+ foregroundOnly = false, doNotAskAgain = true)
+ }
+ }
+ }
+
+ private fun grantUserSelectedVisualGroupPermissions(groupState: GroupState) {
+ val userSelectedPerm =
+ groupState.group.permissions[READ_MEDIA_VISUAL_USER_SELECTED] ?: return
+ if (userSelectedPerm.isImplicit) {
+ val nonSelectedPerms = groupState.group.permissions.keys
+ .filter { it != READ_MEDIA_VISUAL_USER_SELECTED }
+ // If the permission is implicit, grant USER_SELECTED as user set, and all other
+ // permissions as one time, and without app ops.
+ grantForegroundRuntimePermissions(app, groupState.group,
+ listOf(READ_MEDIA_VISUAL_USER_SELECTED))
+ grantForegroundRuntimePermissions(app, groupState.group,
+ nonSelectedPerms, isOneTime = true, userFixed = false, withoutAppOps = true)
+ val appPermGroup = AppPermissionGroup.create(app, packageName,
+ groupState.group.permGroupName, groupState.group.userHandle, false)
+ appPermGroup.setSelfRevoked()
+ appPermGroup.persistChanges(false, null, nonSelectedPerms.toSet())
+ } else {
+ val partialPerms = getPartialStorageGrantPermissionsForGroup(groupState.group).filter {
+ it in groupState.affectedPermissions
+ }
+ val nonSelectedPerms = groupState.affectedPermissions.filter { it !in partialPerms }
+ val setUserFixed = userSelectedPerm.isUserFixed || userSelectedPerm.isUserSet
+ grantForegroundRuntimePermissions(app, groupState.group,
+ partialPerms.toList(), userFixed = setUserFixed)
+ revokeForegroundRuntimePermissions(app, groupState.group,
+ userFixed = setUserFixed, oneTime = false, filterPermissions = nonSelectedPerms)
+ }
+ groupState.state = STATE_GRANTED
+ reportButtonClickResult(groupState, groupState.affectedPermissions, true,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__PHOTOS_SELECTED)
+ }
+
+ @SuppressLint("NewApi")
+ private fun onPermissionGrantResultSingleState(
+ groupState: GroupState,
+ affectedForegroundPermissions: List<String>?,
+ granted: Boolean,
+ foregroundOnly: Boolean,
+ isOneTime: Boolean,
+ doNotAskAgain: Boolean
+ ) {
+ if (!isStateUnknown(groupState.state)) {
+ // We already dealt with this group, don't re-grant/re-revoke
+ return
+ }
+ val shouldAffectBackgroundPermissions =
+ groupState.bgPermissions.isNotEmpty() && !foregroundOnly
+ val shouldAffectForegroundPermssions = groupState.state != STATE_FG_GRANTED_BG_UNKNOWN
+ val result: Int
+ if (granted) {
+ result = if (isOneTime) {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_ONE_TIME
+ } else {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED
+ }
+ if (shouldAffectBackgroundPermissions) {
+ grantBackgroundRuntimePermissions(app, groupState.group,
+ groupState.affectedPermissions)
+ } else if (shouldAffectForegroundPermssions) {
+ if (affectedForegroundPermissions == null) {
+ grantForegroundRuntimePermissions(app, groupState.group,
+ groupState.affectedPermissions, isOneTime)
+ // This prevents weird flag state when app targetSDK switches from S+ to R-
+ if (groupState.affectedPermissions.contains(ACCESS_FINE_LOCATION)) {
+ KotlinUtils.setFlagsWhenLocationAccuracyChanged(
+ app, groupState.group, true)
+ }
+ } else {
+ val newGroup = grantForegroundRuntimePermissions(app,
+ groupState.group, affectedForegroundPermissions, isOneTime)
+ if (!isOneTime || newGroup.isOneTime) {
+ KotlinUtils.setFlagsWhenLocationAccuracyChanged(app, newGroup,
+ affectedForegroundPermissions.contains(ACCESS_FINE_LOCATION))
+ }
+ }
+ }
+ groupState.state = STATE_GRANTED
+ } else {
+ if (shouldAffectBackgroundPermissions) {
+ revokeBackgroundRuntimePermissions(app, groupState.group,
+ userFixed = doNotAskAgain, filterPermissions = groupState.affectedPermissions)
+ } else if (shouldAffectForegroundPermssions) {
+ if (affectedForegroundPermissions == null ||
+ affectedForegroundPermissions.contains(ACCESS_COARSE_LOCATION)) {
+ revokeForegroundRuntimePermissions(app, groupState.group,
+ userFixed = doNotAskAgain,
+ filterPermissions = groupState.affectedPermissions, oneTime = isOneTime)
+ } else {
+ revokeForegroundRuntimePermissions(app, groupState.group,
+ userFixed = doNotAskAgain,
+ filterPermissions = affectedForegroundPermissions, oneTime = isOneTime)
+ }
+ }
+ result = if (doNotAskAgain) {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE
+ } else {
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED
+ }
+ groupState.state = STATE_DENIED
+ }
+ val permissionsChanged = if (foregroundOnly) {
+ groupState.fgPermissions
+ } else {
+ groupState.affectedPermissions
+ }
+ reportButtonClickResult(groupState, permissionsChanged, granted, result)
+ }
+
+ private fun reportButtonClickResult(
+ groupState: GroupState,
+ permissions: Set<String>,
+ granted: Boolean,
+ result: Int
+ ) {
+ reportRequestResult(permissions, result)
+ // group state has changed, reload liveData
+ requestInfosLiveData.update()
+ PermissionDecisionStorageImpl.recordPermissionDecision(app.applicationContext,
+ packageName, groupState.group.permGroupName, granted)
+ PermissionChangeStorageImpl.recordPermissionChange(packageName)
+ if (granted) {
+ startDrivingDecisionReminderServiceIfNecessary(groupState.group.permGroupName)
+ }
+ }
+
+ /**
+ * When distraction optimization is required (the vehicle is in motion), the user may want to
+ * review their permission grants when they are less distracted.
+ */
+ private fun startDrivingDecisionReminderServiceIfNecessary(permGroupName: String) {
+ if (!DeviceUtils.isAuto(app.applicationContext)) {
+ return
+ }
+ DrivingDecisionReminderService.startServiceIfCurrentlyRestricted(
+ Utils.getUserContext(app, user), packageName, permGroupName)
+ }
+
+ private fun getGroupWithPerm(
+ perm: String,
+ groups: List<LightAppPermGroup>
+ ): LightAppPermGroup? {
+ val groupsWithPerm = groups.filter { perm in it.permissions }
+ if (groupsWithPerm.isEmpty()) {
+ return null
+ }
+ return groupsWithPerm.first()
+ }
+
+
+ private fun reportRequestResult(permissions: Collection<String>, result: Int) {
+ permissions.forEach { reportRequestResult(it, result) }
+ }
+
+ /**
+ * Report the result of a grant of a permission.
+ *
+ * @param permission The permission that was granted or denied
+ * @param result The permission grant result
+ */
+ private fun reportRequestResult(permission: String, result: Int) {
+ val isImplicit = permission !in requestedPermissions
+ val isPermissionRationaleShown = shouldShowPermissionRationale(
+ safetyLabelInfoLiveData?.value?.safetyLabel,
+ PermissionMapping.getGroupOfPlatformPermission(permission))
+
+ Log.i(LOG_TAG, "Permission grant result requestId=$sessionId " +
+ "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " +
+ "isImplicit=$isImplicit result=$result " +
+ "isPermissionRationaleShown=$isPermissionRationaleShown")
+
+ PermissionControllerStatsLog.write(
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED, sessionId,
+ packageInfo.uid, packageName, permission, isImplicit, result,
+ isPermissionRationaleShown)
+ }
+
+ /**
+ * Save the group states of the view model, to allow for state restoration after lifecycle
+ * events
+ *
+ * @param outState The bundle in which to store state
+ */
+ override fun saveInstanceState(outState: Bundle) {
+ for ((groupName, groupState) in groupStates) {
+ outState.putInt(groupName, groupState.state)
+ }
+ }
+
+ /**
+ * Determine if the activity should return permission state to the caller
+ *
+ * @return Whether or not state should be returned. False only if the package is pre-M, true
+ * otherwise.
+ */
+ override fun shouldReturnPermissionState(): Boolean {
+ return if (packageInfoLiveData.value != null) {
+ packageInfoLiveData.value!!.targetSdkVersion >= Build.VERSION_CODES.M
+ } else {
+ // Should not be reached, as this method shouldn't be called before data is passed to
+ // the activity for the first time
+ try {
+ Utils.getUserContext(app, user).packageManager
+ .getApplicationInfo(packageName, 0).targetSdkVersion >= Build.VERSION_CODES.M
+ } catch (e: PackageManager.NameNotFoundException) {
+ true
+ }
+ }
+ }
+
+ override fun handleHealthConnectPermissions(activity: Activity) {
+ if (activityResultCallback == null) {
+ activityResultCallback = Consumer {
+ groupStates[HEALTH_PERMISSION_GROUP]?.state = STATE_SKIPPED
+ requestInfosLiveData.update()
+ }
+ val healthPermissions = unfilteredAffectedPermissions.filter { permission ->
+ isHealthPermission(activity, permission)
+ }.toTypedArray()
+ val intent: Intent = Intent(ACTION_REQUEST_HEALTH_PERMISSIONS)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ .putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, healthPermissions)
+ .putExtra(Intent.EXTRA_USER, Process.myUserHandle())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
+ }
+ }
+
+ /**
+ * Send the user directly to the AppPermissionFragment. Used for R+ apps.
+ *
+ * @param activity The current activity
+ * @param groupName The name of the permission group whose fragment should be opened
+ */
+ override fun sendDirectlyToSettings(activity: Activity, groupName: String) {
+ if (activityResultCallback == null) {
+ activityResultCallback = Consumer { data ->
+ if (data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED) == null) {
+ // User didn't interact, count against rate limit
+ val group = groupStates[groupName]?.group ?: return@Consumer
+ if (group.background.isUserSet) {
+ KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_FIXED to true,
+ filterPermissions = group.backgroundPermNames)
+ } else {
+ KotlinUtils.setGroupFlags(app, group, FLAG_PERMISSION_USER_SET to true,
+ filterPermissions = group.backgroundPermNames)
+ }
+ }
+
+ groupStates[groupName]?.state = STATE_SKIPPED
+ // Update our liveData now that there is a new skipped group
+ requestInfosLiveData.update()
+ }
+ startAppPermissionFragment(activity, groupName)
+ }
+ }
+
+ override fun openPhotoPicker(activity: Activity, result: Int) {
+ if (activityResultCallback != null) {
+ return
+ }
+ if (groupStates[READ_MEDIA_VISUAL]?.affectedPermissions == null) {
+ return
+ }
+ activityResultCallback = Consumer { data ->
+ val anySelected = data?.getBooleanExtra(INTENT_PHOTOS_SELECTED, true) == true
+ if (anySelected) {
+ onPermissionGrantResult(READ_MEDIA_VISUAL, null, result)
+ } else {
+ onPermissionGrantResult(READ_MEDIA_VISUAL, null, CANCELED)
+ }
+ requestInfosLiveData.update()
+ }
+ activity.startActivityForResult(Intent(MediaStore.ACTION_USER_SELECT_IMAGES_FOR_APP)
+ .putExtra(Intent.EXTRA_UID, packageInfo.uid)
+ .setType(KotlinUtils.getMimeTypeForPermissions(unfilteredAffectedPermissions)),
+ PHOTO_PICKER_REQUEST_CODE)
+ }
+
+ /**
+ * Send the user to the AppPermissionFragment from a link. Used for Q- apps
+ *
+ * @param activity The current activity
+ * @param groupName The name of the permission group whose fragment should be opened
+ */
+ override fun sendToSettingsFromLink(activity: Activity, groupName: String) {
+ startAppPermissionFragment(activity, groupName)
+ activityResultCallback = Consumer { data ->
+ val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
+ if (returnGroupName != null) {
+ groupStates[returnGroupName]?.state = STATE_SKIPPED
+ val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, -1)
+ logSettingsInteraction(returnGroupName, result)
+ requestInfosLiveData.update()
+ }
+ }
+ }
+
+ /**
+ * Shows the Permission Rationale Dialog. For use with U+ only, otherwise no-op.
+ *
+ * @param activity The current activity
+ * @param groupName The name of the permission group whose fragment should be opened
+ */
+ override fun showPermissionRationaleActivity(activity: Activity, groupName: String) {
+ if (!SdkLevel.isAtLeastU()) {
+ return
+ }
+
+ val intent = Intent(activity, PermissionRationaleActivity::class.java).apply {
+ putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ }
+ activityResultCallback = Consumer { data ->
+ val returnGroupName = data?.getStringExtra(EXTRA_RESULT_PERMISSION_INTERACTED)
+ if (returnGroupName != null) {
+ groupStates[returnGroupName]?.state = STATE_SKIPPED
+ val result = data.getIntExtra(EXTRA_RESULT_PERMISSION_RESULT, CANCELED)
+ logSettingsInteraction(returnGroupName, result)
+ requestInfosLiveData.update()
+ }
+ }
+ activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
+ }
+
+ private fun startAppPermissionFragment(activity: Activity, groupName: String) {
+ val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSION)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ .putExtra(Intent.EXTRA_USER, user)
+ .putExtra(ManagePermissionsActivity.EXTRA_CALLER_NAME,
+ GrantPermissionsActivity::class.java.name)
+ .putExtra(Constants.EXTRA_SESSION_ID, sessionId)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ activity.startActivityForResult(intent, APP_PERMISSION_REQUEST_CODE)
+ }
+
+ private fun getGrantBehavior(group: LightAppPermGroup): GrantBehavior {
+ return when (group.permGroupName) {
+ LOCATION -> LocationGrantBehavior
+ HEALTH_PERMISSION_GROUP -> HealthGrantBehavior
+ NOTIFICATIONS -> NotificationGrantBehavior
+ STORAGE, READ_MEDIA_VISUAL, READ_MEDIA_AURAL -> StorageGrantBehavior
+ else -> {
+ if (Utils.hasPermWithBackgroundModeCompat(group)) {
+ BackgroundGrantBehavior
+ } else {
+ BasicGrantBehavior
+ }
+ }
+ }
+ }
+
+ private fun logSettingsInteraction(groupName: String, result: Int) {
+ val groupState = groupStates[groupName] ?: return
+ val backgroundPerms = groupState.affectedPermissions.filter {
+ it in groupState.group.backgroundPermNames
+ }
+ val foregroundPerms = groupState.affectedPermissions.filter {
+ it !in backgroundPerms }
+ val deniedPrejudiceInSettings =
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_WITH_PREJUDICE_IN_SETTINGS
+ when (result) {
+ GRANTED_ALWAYS -> {
+ reportRequestResult(groupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS)
+ }
+ GRANTED_FOREGROUND_ONLY -> {
+ reportRequestResult(foregroundPerms,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_GRANTED_IN_SETTINGS)
+ if (backgroundPerms.isNotEmpty()) {
+ reportRequestResult(backgroundPerms,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS)
+ }
+ }
+ DENIED -> {
+ reportRequestResult(groupState.affectedPermissions,
+ PERMISSION_GRANT_REQUEST_RESULT_REPORTED__RESULT__USER_DENIED_IN_SETTINGS)
+ }
+ DENIED_DO_NOT_ASK_AGAIN -> {
+ reportRequestResult(groupState.affectedPermissions, deniedPrejudiceInSettings)
+ }
+ }
+ }
+
+ /**
+ * Log all permission groups which were requested
+ */
+ override fun logRequestedPermissionGroups() {
+ if (groupStates.isEmpty()) {
+ return
+ }
+ val groups = groupStates.map { it.value.group }
+ SafetyNetLogger.logPermissionsRequested(packageName, packageInfo.uid, groups)
+ }
+
+ /**
+ * Log information about the buttons which were shown and clicked by the user.
+ *
+ * @param groupName The name of the permission group which was interacted with
+ * @param selectedPrecision Selected precision of the location permission - bit flags indicate
+ * which locations were chosen
+ * @param clickedButton The button that was clicked by the user
+ * @param presentedButtons All buttons which were shown to the user
+ */
+ override fun logClickedButtons(
+ groupName: String?,
+ selectedPrecision: Int,
+ clickedButton: Int,
+ presentedButtons: Int,
+ isPermissionRationaleShown: Boolean
+ ) {
+ if (groupName == null) {
+ return
+ }
+
+ if (!requestInfosLiveData.isInitialized || !packageInfoLiveData.isInitialized) {
+ Log.wtf(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
+ "$groupName package=$packageName presentedButtons=$presentedButtons " +
+ "clickedButton=$clickedButton isPermissionRationaleShown=" +
+ "$isPermissionRationaleShown sessionId=$sessionId, but requests were not yet" +
+ "initialized", IllegalStateException())
+ return
+ }
+
+ PermissionControllerStatsLog.write(GRANT_PERMISSIONS_ACTIVITY_BUTTON_ACTIONS,
+ groupName, packageInfo.uid, packageName, presentedButtons, clickedButton, sessionId,
+ packageInfo.targetSdkVersion, selectedPrecision,
+ isPermissionRationaleShown)
+ Log.i(LOG_TAG, "Logged buttons presented and clicked permissionGroupName=" +
+ "$groupName uid=${packageInfo.uid} selectedPrecision=$selectedPrecision " +
+ "package=$packageName presentedButtons=$presentedButtons " +
+ "clickedButton=$clickedButton isPermissionRationaleShown=" +
+ "$isPermissionRationaleShown sessionId=$sessionId " +
+ "targetSdk=${packageInfo.targetSdkVersion}")
+ }
+
+ /**
+ * Use the autoGrantNotifier to notify of auto-granted permissions.
+ */
+ override fun autoGrantNotify() {
+ autoGrantNotifier?.notifyOfAutoGrantPermissions(true)
+ }
+
+ // TODO: 284183336, once the old viewModel is gone, this should be moved to the activity
+ private fun convertPromptToRequestInfo(
+ groupState: GroupState,
+ prompt: Prompt,
+ deny: DenyButton
+ ): RequestInfo {
+ val buttons = mutableSetOf<Int>()
+ val locationButtons = mutableSetOf<Int>()
+ var message = RequestMessage.FG_MESSAGE
+ var detailMessage = RequestMessage.NO_MESSAGE
+ when (prompt) {
+ Prompt.BASIC -> buttons.add(ALLOW_BUTTON)
+ Prompt.FG_ONLY -> buttons.add(ALLOW_FOREGROUND_BUTTON)
+ Prompt.ONE_TIME_FG ->
+ buttons.addAll(listOf(ALLOW_FOREGROUND_BUTTON, ALLOW_ONE_TIME_BUTTON))
+ Prompt.SETTINGS_LINK_FOR_BG -> {
+ buttons.add(ALLOW_FOREGROUND_BUTTON)
+ message = RequestMessage.BG_MESSAGE
+ detailMessage = RequestMessage.BG_MESSAGE
+ }
+ Prompt.SETTINGS_LINK_WITH_OT -> {
+ buttons.addAll(listOf(ALLOW_FOREGROUND_BUTTON, ALLOW_ONE_TIME_BUTTON))
+ message = RequestMessage.BG_MESSAGE
+ detailMessage = RequestMessage.BG_MESSAGE
+ }
+ Prompt.UPGRADE_SETTINGS_LINK -> {
+ message = RequestMessage.UPGRADE_MESSAGE
+ detailMessage = RequestMessage.UPGRADE_MESSAGE
+ }
+ Prompt.OT_UPGRADE_SETTINGS_LINK -> {
+ message = RequestMessage.UPGRADE_MESSAGE
+ detailMessage = RequestMessage.UPGRADE_MESSAGE
+ }
+ Prompt.LOCATION_TWO_BUTTON -> {
+ buttons.addAll(listOf(ALLOW_FOREGROUND_BUTTON, ALLOW_ONE_TIME_BUTTON))
+ locationButtons.addAll(listOf(LOCATION_ACCURACY_LAYOUT,
+ DIALOG_WITH_BOTH_LOCATIONS, getSelectedLocation(groupState.group)))
+ }
+ Prompt.LOCATION_COARSE_ONLY -> {
+ buttons.addAll(listOf(ALLOW_FOREGROUND_BUTTON, ALLOW_ONE_TIME_BUTTON))
+ locationButtons.addAll(listOf(LOCATION_ACCURACY_LAYOUT,
+ DIALOG_WITH_COARSE_LOCATION_ONLY))
+ message = RequestMessage.FG_COARSE_LOCATION_MESSAGE
+ }
+ Prompt.LOCATION_FINE_UPGRADE -> {
+ buttons.addAll(listOf(ALLOW_FOREGROUND_BUTTON, ALLOW_ONE_TIME_BUTTON))
+ locationButtons.addAll(listOf(LOCATION_ACCURACY_LAYOUT,
+ DIALOG_WITH_FINE_LOCATION_ONLY))
+ message = RequestMessage.FG_FINE_LOCATION_MESSAGE
+ }
+ Prompt.SELECT_PHOTOS -> {
+ buttons.addAll(listOf(ALLOW_ALL_BUTTON, ALLOW_SELECTED_BUTTON))
+ }
+ Prompt.SELECT_MORE_PHOTOS -> {
+ buttons.addAll(listOf(ALLOW_ALL_BUTTON, ALLOW_SELECTED_BUTTON))
+ message = GrantPermissionsViewModel.Companion.RequestMessage.MORE_PHOTOS_MESSAGE
+ }
+ Prompt.STORAGE_SUPERGROUP_PRE_Q -> {
+ buttons.add(ALLOW_BUTTON)
+ message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_PRE_Q
+ }
+ Prompt.STORAGE_SUPERGROUP_Q_TO_S -> {
+ buttons.add(ALLOW_BUTTON)
+ message = RequestMessage.STORAGE_SUPERGROUP_MESSAGE_Q_TO_S
+ }
+ Prompt.NO_UI_SETTINGS_REDIRECT -> {
+ return RequestInfo(groupState.group.permGroupInfo, sendToSettingsImmediately = true)
+ }
+ Prompt.NO_UI_PHOTO_PICKER_REDIRECT -> {
+ return RequestInfo(groupState.group.permGroupInfo, openPhotoPicker = true)
+ }
+ Prompt.NO_UI_HEALTH_REDIRECT -> {
+ return RequestInfo(groupState.group.permGroupInfo)
+ }
+ Prompt.NO_UI_FILTER_THIS_GROUP -> {
+ return RequestInfo(groupState.group.permGroupInfo,
+ filteredPermissions = groupState.affectedPermissions)
+ }
+ Prompt.NO_UI_REJECT_ALL_GROUPS, Prompt.NO_UI_REJECT_THIS_GROUP -> {
+ /* These have no buttons */
+ }
+ }
+
+ when (deny) {
+ DenyButton.DENY -> buttons.add(DENY_BUTTON)
+ DenyButton.DENY_DONT_ASK_AGAIN -> buttons.add(DENY_AND_DONT_ASK_AGAIN_BUTTON)
+ DenyButton.DONT_SELECT_MORE -> buttons.add(DONT_ALLOW_MORE_SELECTED_BUTTON)
+ DenyButton.NO_UPGRADE -> buttons.add(NO_UPGRADE_BUTTON)
+ DenyButton.NO_UPGRADE_OT -> buttons.add(NO_UPGRADE_OT_BUTTON)
+ DenyButton.NO_UPGRADE_AND_DONT_ASK_AGAIN ->
+ buttons.add(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON)
+ DenyButton.NO_UPGRADE_AND_DONT_ASK_AGAIN_OT -> NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON
+ DenyButton.NONE -> {}
+ }
+
+ val safetyLabel = safetyLabelInfoLiveData?.value?.safetyLabel
+ if (shouldShowPermissionRationale(safetyLabel, groupState.group.permGroupName)) {
+ buttons.add(LINK_TO_PERMISSION_RATIONALE)
+ }
+ val buttonArray = convertSetToBoolList(buttons, NEXT_BUTTON)
+ val locationArray = convertSetToBoolList(locationButtons, NEXT_LOCATION_DIALOG)
+
+ val permissionResourceDeviceId = ContextCompat.DEVICE_ID_DEFAULT
+ // TODO(b/298623935) Determine the device ID of the permission resource
+ // More logic is required at that point to properly identify permissions which can be
+ // device-aware (once implemented)
+ // e.g. check VDM for the VirtualDevice's capabilities
+ // e.g. check the permission request for the target device ID.
+
+ return RequestInfo(groupState.group.permGroupInfo, buttonArray, locationArray, message,
+ detailMessage, deviceId = permissionResourceDeviceId)
+ }
+
+ private fun getSelectedLocation(group: LightAppPermGroup): Int {
+ // Steps to decide location accuracy default state
+ // 1. If none of the FINE and COARSE isSelectedLocationAccuracy
+ // flags is set, then use default precision from device config.
+ // 2. Otherwise set to whichever isSelectedLocationAccuracy is true.
+ val coarseLocationPerm =
+ group.allPermissions[ACCESS_COARSE_LOCATION]
+ val fineLocationPerm =
+ group.allPermissions[ACCESS_FINE_LOCATION]
+ return if (coarseLocationPerm?.isSelectedLocationAccuracy == false &&
+ fineLocationPerm?.isSelectedLocationAccuracy == false) {
+ if (KotlinUtils.getDefaultPrecision()) {
+ FINE_RADIO_BUTTON
+ } else {
+ COARSE_RADIO_BUTTON
+ }
+ } else if (coarseLocationPerm?.isSelectedLocationAccuracy == true) {
+ COARSE_RADIO_BUTTON
+ } else {
+ FINE_RADIO_BUTTON
+ }
+ }
+
+ private fun convertSetToBoolList(buttonSet: Set<Int>, maxSize: Int): List<Boolean> {
+ val buttonArray = MutableList(maxSize) { false }
+ for (button in buttonSet) {
+ buttonArray[button] = true
+ }
+ return buttonArray
+ }
+
+ private fun isStateUnknown(state: Int?): Boolean {
+ return state == null || state == STATE_UNKNOWN || state == STATE_FG_GRANTED_BG_UNKNOWN
+ }
+
+ companion object {
+ const val APP_PERMISSION_REQUEST_CODE = 1
+ const val PHOTO_PICKER_REQUEST_CODE = 2
+ private const val STATE_UNKNOWN = 0
+ private const val STATE_GRANTED = 1
+ private const val STATE_DENIED = 2
+ private const val STATE_SKIPPED = 3
+ private const val STATE_FG_GRANTED_BG_UNKNOWN = 4
+ }
+}
+
+/**
+ * Factory for an AppPermissionViewModel
+ *
+ * @param app The current application
+ * @param packageName The name of the package this ViewModel represents
+ */
+class NewGrantPermissionsViewModelFactory(
+ private val app: Application,
+ private val packageName: String,
+ private val requestedPermissions: List<String>,
+ private val systemRequestedPermissions: List<String>,
+ private val sessionId: Long,
+ private val savedState: Bundle?
+) : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return NewGrantPermissionsViewModel(app, packageName, requestedPermissions,
+ systemRequestedPermissions, sessionId, savedState) as T
+ }
+}
+
+enum class Prompt {
+ BASIC, // Allow/Deny
+ ONE_TIME_FG, // Allow in foreground/one time/deny
+ FG_ONLY, // Allow in foreground/deny
+ SETTINGS_LINK_FOR_BG, // Allow in foreground/deny, with link to settings to change background
+ SETTINGS_LINK_WITH_OT, // Same as above, but with a one time button
+ UPGRADE_SETTINGS_LINK, // Keep foreground, with link to settings to grant background
+ OT_UPGRADE_SETTINGS_LINK, // Same as above, but the button is "keep one time"
+ LOCATION_TWO_BUTTON, // Choose coarse/fine, foreground/one time/deny
+ LOCATION_COARSE_ONLY, // Only coarse location, foreground/one time/deny
+ LOCATION_FINE_UPGRADE, // Upgrade coarse to fine, upgrade to fine/ one time/ keep coarse
+ SELECT_PHOTOS, // Select photos/allow all photos/deny
+ SELECT_MORE_PHOTOS, // Select more photos/allow all photos/don't allow more
+ // These next two are for T+ devices, and < T apps. They request the old "storage" group, and
+ // we "grant" it, while actually granting the new visual and audio groups
+ STORAGE_SUPERGROUP_Q_TO_S, // Allow/deny, special message
+ STORAGE_SUPERGROUP_PRE_Q, // Allow/deny, special message (different from above)
+ NO_UI_SETTINGS_REDIRECT, // Send the user directly to permission settings
+ NO_UI_PHOTO_PICKER_REDIRECT, // Send the user directly to the photo picker
+ NO_UI_HEALTH_REDIRECT, // Send the user directly to the Health Connect settings
+ NO_UI_REJECT_THIS_GROUP, // Auto deny this permission group
+ NO_UI_REJECT_ALL_GROUPS, // Auto deny all permission groups in this request
+ NO_UI_FILTER_THIS_GROUP, // Do not act on this permission group. Remove it from results.
+}
+
+enum class DenyButton {
+ DENY,
+ DENY_DONT_ASK_AGAIN,
+ NO_UPGRADE,
+ NO_UPGRADE_OT,
+ NO_UPGRADE_AND_DONT_ASK_AGAIN,
+ NO_UPGRADE_AND_DONT_ASK_AGAIN_OT,
+ DONT_SELECT_MORE, // used in the SELECT_MORE_PHOTOS dialog
+ NONE,
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
index 114b8e045..1caed6ee1 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt
@@ -96,8 +96,7 @@ class PermissionAppsViewModel(
val categorizedAppsLiveData = CategorizedAppsLiveData(groupName)
@get:RequiresApi(Build.VERSION_CODES.S)
- val sensorStatusLiveData: SensorStatusLiveData by lazy(LazyThreadSafetyMode.NONE)
- @RequiresApi(Build.VERSION_CODES.S) {
+ val sensorStatusLiveData: SensorStatusLiveData by lazy(LazyThreadSafetyMode.NONE) {
SensorStatusLiveData()
}
@@ -442,11 +441,11 @@ class PermissionAppsViewModel(
val uid = getPackageUid(application,
packageName, user) ?: return
PermissionControllerStatsLog.write(
- PermissionControllerStatsLog.PERMISSION_APPS_FRAGMENT_VIEWED, sessionId, viewId,
- permGroupName, uid, packageName, category)
- Log.v(tag, tag + " created with sessionId=" + sessionId +
- " permissionGroupName=" + permGroupName + " appUid=" + uid +
- " packageName=" + packageName + " category=" + category)
+ PermissionControllerStatsLog.PERMISSION_APPS_FRAGMENT_VIEWED, sessionId, viewId,
+ permGroupName, uid, packageName, category)
+ Log.i(tag, tag + " created with sessionId=" + sessionId +
+ " permissionGroupName=" + permGroupName + " appUid=" + uid +
+ " packageName=" + packageName + " category=" + category)
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BackgroundGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BackgroundGrantBehavior.kt
new file mode 100644
index 000000000..071692d65
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BackgroundGrantBehavior.kt
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import android.os.Build
+import android.permission.PermissionManager
+import android.util.Log
+import com.android.permissioncontroller.PermissionControllerApplication
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+import com.android.permissioncontroller.permission.utils.PermissionMapping
+
+/**
+ * This behavior handles groups that respect the difference between foreground and background
+ * access. At present, this includes all one-time permissions, in addition to those with explicit
+ * background permissions.
+ *
+ * The behavior is split based on the target SDK when the app split into foreground and background
+ * (or android R, whichever is newer). If the app targets prior to the split, we show a dialog with
+ * a link to permission settings. Once the app targets after the split, we no longer allow the app
+ * to request background and foreground at the same time. If they try, we reject it. An app has to
+ * request foreground, get it granted, then request background only, we send the user to settings.
+ */
+object BackgroundGrantBehavior : GrantBehavior() {
+
+ private val splitPermissionSdkMap = buildMap {
+ for (splitPerm in
+ PermissionControllerApplication.get()
+ .getSystemService(PermissionManager::class.java)!!
+ .splitPermissions) {
+ put(splitPerm.splitPermission, splitPerm.targetSdk)
+ }
+ }
+
+ // Redundant "if" conditions are suppressed, because the conditions are clearer
+ @Suppress("KotlinConstantConditions")
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ val requestsBg = hasBgPerms(group, requestedPerms)
+ val requestsFg = requestedPerms.any { it !in group.backgroundPermNames }
+ val isOneTimeGroup = PermissionMapping.supportsOneTimeGrant(group.permGroupName)
+ val isFgGranted = group.foreground.isGrantedExcludingRWROrAllRWR
+ val isFgOneTime = group.foreground.isOneTime
+ val splitSdk = getSdkGroupWasSplitToBg(requestedPerms)
+ val isAppIsOlderThanSplitToBg = group.packageInfo.targetSdkVersion < splitSdk
+
+ if (!requestsBg && !isOneTimeGroup) {
+ return Prompt.FG_ONLY
+ } else if (!requestsBg) {
+ return Prompt.ONE_TIME_FG
+ }
+
+ if (requestsBg && !requestsFg && !isFgGranted) {
+ Log.w(
+ LOG_TAG,
+ "Cannot grant ${group.permGroupName} as the foreground permissions" +
+ " are not requested or already granted.")
+ return Prompt.NO_UI_REJECT_THIS_GROUP
+ }
+
+ return if (isAppIsOlderThanSplitToBg) {
+ getPromptForOlderApp(isOneTimeGroup, requestsFg, isFgGranted, isFgOneTime)
+ } else {
+ getPromptForNewerApp(group.permGroupName, splitSdk, requestsFg, isFgGranted)
+ }
+ }
+
+ /**
+ * Get the prompt for an app that targets before the sdk level where the permission group was
+ * split into foreground and background.
+ */
+ private fun getPromptForOlderApp(
+ isOneTimeGroup: Boolean,
+ requestsFg: Boolean,
+ isFgGranted: Boolean,
+ isFgOneTime: Boolean
+ ): Prompt {
+ if (requestsFg && !isFgGranted) {
+ if (isOneTimeGroup) {
+ return Prompt.SETTINGS_LINK_WITH_OT
+ }
+ return Prompt.SETTINGS_LINK_FOR_BG
+ }
+
+ if (isFgGranted) {
+ if (isFgOneTime) {
+ return Prompt.OT_UPGRADE_SETTINGS_LINK
+ }
+ return Prompt.UPGRADE_SETTINGS_LINK
+ }
+ return Prompt.NO_UI_REJECT_ALL_GROUPS
+ }
+
+ /**
+ * Get the prompt for an app that targets at least the sdk level where the permission group was
+ * split into foreground and background.
+ */
+ private fun getPromptForNewerApp(
+ groupName: String,
+ splitSdk: Int,
+ requestsFg: Boolean,
+ isFgGranted: Boolean
+ ): Prompt {
+ if (!requestsFg && isFgGranted) {
+ return Prompt.NO_UI_SETTINGS_REDIRECT
+ }
+
+ if (requestsFg) {
+ Log.e(
+ LOG_TAG,
+ "For SDK $splitSdk+ apps requesting $groupName, " +
+ "background permissions must be requested alone after foreground permissions " +
+ "are already granted")
+ return Prompt.NO_UI_REJECT_ALL_GROUPS
+ } else if (!isFgGranted) {
+ Log.e(
+ LOG_TAG,
+ "For SDK $splitSdk+ apps requesting, $groupName, " +
+ "background permissions must be requested after foreground permissions are " +
+ "already granted")
+ Prompt.NO_UI_REJECT_THIS_GROUP
+ }
+ return Prompt.NO_UI_REJECT_ALL_GROUPS
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ val basicDenyBehavior = BasicGrantBehavior.getDenyButton(group, requestedPerms, prompt)
+ if (prompt == Prompt.UPGRADE_SETTINGS_LINK || prompt == Prompt.OT_UPGRADE_SETTINGS_LINK) {
+ if (basicDenyBehavior == DenyButton.DENY) {
+ return if (prompt == Prompt.UPGRADE_SETTINGS_LINK) {
+ DenyButton.NO_UPGRADE
+ } else {
+ DenyButton.NO_UPGRADE_OT
+ }
+ }
+ return if (prompt == Prompt.UPGRADE_SETTINGS_LINK) {
+ DenyButton.NO_UPGRADE_AND_DONT_ASK_AGAIN
+ } else {
+ DenyButton.NO_UPGRADE_AND_DONT_ASK_AGAIN_OT
+ }
+ }
+ return basicDenyBehavior
+ }
+
+ override fun isGroupFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ return (!hasBgPerms(group, requestedPerms) ||
+ group.background.isGrantedExcludingRWROrAllRWR) &&
+ group.foreground.isGrantedExcludingRWROrAllRWR
+ }
+
+ override fun isForegroundFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ return group.foreground.isGrantedExcludingRWROrAllRWR
+ }
+
+ override fun isPermissionFixed(group: LightAppPermGroup, perm: String): Boolean {
+ if (perm in group.backgroundPermNames) {
+ return group.background.isUserFixed
+ }
+ return group.foreground.isUserFixed
+ }
+
+ private fun hasBgPerms(group: LightAppPermGroup, requestedPerms: Set<String>): Boolean {
+ return requestedPerms.any { it in group.backgroundPermNames }
+ }
+
+ private fun getSdkGroupWasSplitToBg(requestedPerms: Set<String>): Int {
+ val splitSdks = requestedPerms.mapNotNull { perm -> splitPermissionSdkMap[perm] }
+
+ if (splitSdks.isEmpty()) {
+ // If there was no split found, assume the split happened in R. This applies to
+ // Mic and Camera, which technically split in S, but were treated as foreground-only
+ // in R
+ return Build.VERSION_CODES.R
+ }
+ // The background permission request UI changed in R, so if a split happened before R,
+ // treat it as if it happened in R
+ return maxOf(splitSdks.min(), Build.VERSION_CODES.R)
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BasicGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BasicGrantBehavior.kt
new file mode 100644
index 000000000..b97212f94
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/BasicGrantBehavior.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+
+/**
+ * A basic group. Shows "allow" and "deny", does not allow fixed permissions to be re-requested
+ */
+object BasicGrantBehavior : GrantBehavior() {
+
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ return Prompt.BASIC
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ if (prompt in noDenyButtonPrompts) {
+ return DenyButton.NONE
+ }
+ if (group.isUserSet) {
+ return DenyButton.DENY_DONT_ASK_AGAIN
+ }
+ return DenyButton.DENY
+ }
+
+ // A list of prompts without any deny behavior
+ private val noDenyButtonPrompts = listOf(Prompt.NO_UI_SETTINGS_REDIRECT,
+ Prompt.NO_UI_PHOTO_PICKER_REDIRECT, Prompt.NO_UI_HEALTH_REDIRECT,
+ Prompt.NO_UI_REJECT_THIS_GROUP, Prompt.NO_UI_REJECT_ALL_GROUPS,
+ Prompt.NO_UI_FILTER_THIS_GROUP)
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/GrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/GrantBehavior.kt
new file mode 100644
index 000000000..b92281272
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/GrantBehavior.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+
+/**
+ * The base behavior all grant behavior objects inherit from.
+ */
+abstract class GrantBehavior {
+ val LOG_TAG = "GrantPermissionsViewModel"
+
+ /**
+ * Get the prompt type for the given set of requested permissions
+ * @param group The LightAppPermGroup representing the state of the app and its permissions
+ * @param requestedPerms The permissions requested by the app, after filtering
+ * @param isSystemTriggeredPrompt Whether the prompt was triggered by the system, instead of
+ * by the app.
+ */
+ abstract fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean = false
+ ): Prompt
+
+ /**
+ * Get the deny button type for the given set of requested permissions. This is separate from
+ * the prompt, because the same prompt can have multiple deny behaviors, based on if the user
+ * has seen it before.
+ * @param group The LightAppPermGroup representing the state of the app and its permissions
+ * @param requestedPerms The permissions requested by the app, after filtering
+ * @param prompt The prompt determined by the behavior.
+ */
+ abstract fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton
+
+ /**
+ * Whether the group is considered "fully granted". If it is, any remaining permissions in the
+ * group not already granted will be granted.
+ */
+ open fun isGroupFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ return group.foreground.isGrantedExcludingRWROrAllRWR
+ }
+
+ /**
+ * Whether or not all foreground permissions in the group are granted. Only different in groups
+ * that respect background and foreground permissions.
+ */
+ open fun isForegroundFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ return isGroupFullyGranted(group, requestedPerms)
+ }
+
+ /**
+ * Whether or not the permission should be considered as "user fixed". If it is, it is removed
+ * from the request.
+ */
+ open fun isPermissionFixed(group: LightAppPermGroup, perm: String): Boolean {
+ return group.isUserFixed
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/HealthGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/HealthGrantBehavior.kt
new file mode 100644
index 000000000..7bc520c22
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/HealthGrantBehavior.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+
+/**
+ * Health permissions always redirect to the health connect UI.
+ */
+object HealthGrantBehavior : GrantBehavior() {
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ return Prompt.NO_UI_HEALTH_REDIRECT
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ return DenyButton.NONE
+ }
+
+ override fun isGroupFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ return requestedPerms.all { group.permissions[it]?.isGrantedIncludingAppOp != false }
+ }
+
+ override fun isPermissionFixed(group: LightAppPermGroup, perm: String): Boolean {
+ return group.permissions[perm]?.isUserFixed == true
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/LocationGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/LocationGrantBehavior.kt
new file mode 100644
index 000000000..c541c4f4d
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/LocationGrantBehavior.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.os.Build
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+import com.android.permissioncontroller.permission.utils.KotlinUtils
+
+/**
+ * The Location Grant behavior is the same as the Background group behavior, up until S. After S,
+ * the fine and coarse location permissions were allowed to be granted separately, and this created
+ * a new set of grant dialogs.
+ */
+object LocationGrantBehavior : GrantBehavior() {
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ val backgroundPrompt = BackgroundGrantBehavior.getPrompt(group, requestedPerms)
+ val requestsBackground = requestedPerms.any { it in group.backgroundPermNames }
+ val coarseGranted =
+ group.permissions[ACCESS_COARSE_LOCATION]?.isGrantedIncludingAppOp == true
+ return if (!supportsLocationAccuracy(group) || requestsBackground) {
+ backgroundPrompt
+ } else if (requestedPerms.contains(ACCESS_FINE_LOCATION)) {
+ if (coarseGranted) {
+ Prompt.LOCATION_FINE_UPGRADE
+ } else {
+ Prompt.LOCATION_TWO_BUTTON
+ }
+ } else if (requestedPerms.contains(ACCESS_COARSE_LOCATION) && !coarseGranted) {
+ Prompt.LOCATION_COARSE_ONLY
+ } else {
+ backgroundPrompt
+ }
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ return BackgroundGrantBehavior.getDenyButton(group, requestedPerms, prompt)
+ }
+
+ override fun isGroupFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ val requestsBackground = requestedPerms.any { it in group.backgroundPermNames }
+ if (!supportsLocationAccuracy(group) || requestsBackground) {
+ return BackgroundGrantBehavior.isGroupFullyGranted(group, requestedPerms)
+ }
+ return isForegroundFullyGranted(group, requestedPerms)
+ }
+
+ override fun isForegroundFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ if (!supportsLocationAccuracy(group)) {
+ return BackgroundGrantBehavior.isForegroundFullyGranted(group, requestedPerms)
+ }
+
+ if (requestedPerms.contains(ACCESS_FINE_LOCATION)) {
+ return group.permissions[ACCESS_FINE_LOCATION]?.isGrantedIncludingAppOp == true
+ }
+
+ return group.foreground.isGrantedExcludingRWROrAllRWR
+ }
+
+ override fun isPermissionFixed(group: LightAppPermGroup, perm: String): Boolean {
+ if (!supportsLocationAccuracy(group) || perm != ACCESS_COARSE_LOCATION) {
+ return BackgroundGrantBehavior.isPermissionFixed(group, perm)
+ }
+
+ // If the location group is user fixed but ACCESS_COARSE_LOCATION is not, then
+ // ACCESS_FINE_LOCATION must be user fixed. In this case ACCESS_COARSE_LOCATION
+ // is still grantable.
+ return group.foreground.isUserFixed && group.permissions[perm]?.isUserFixed == true
+ }
+
+ private fun supportsLocationAccuracy(group: LightAppPermGroup): Boolean {
+ return KotlinUtils.isLocationAccuracyEnabled() &&
+ group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.S
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/NotificationGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/NotificationGrantBehavior.kt
new file mode 100644
index 000000000..0245f7b8e
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/NotificationGrantBehavior.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import android.os.Build.VERSION_CODES.TIRAMISU
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+
+/**
+ * The Notification permission behavior is similar to basic, except:
+ *
+ * It can be triggered by the system. If it's system triggered we only show it until the user makes
+ * one decision. We don't make the user show it twice.
+ *
+ * It can't be explicitly requested from apps that don't yet target android T. If they try, we
+ * remove it entirely from the request, do not return a result, and take no action on it.
+ *
+ */
+object NotificationGrantBehavior : GrantBehavior() {
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ val isPreT = group.packageInfo.targetSdkVersion < TIRAMISU
+ if (!isSystemTriggeredPrompt && isPreT) {
+ // Apps targeting below T cannot manually request Notifications
+ return Prompt.NO_UI_FILTER_THIS_GROUP
+ } else if (isPreT && group.isUserSet) {
+ // If the user has seen the system-triggered prompt once, don't show it again
+ return Prompt.NO_UI_FILTER_THIS_GROUP
+ }
+ return BasicGrantBehavior.getPrompt(group, requestedPerms, isSystemTriggeredPrompt)
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ return BasicGrantBehavior.getDenyButton(group, requestedPerms, prompt)
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/StorageGrantBehavior.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/StorageGrantBehavior.kt
new file mode 100644
index 000000000..719c5567a
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/grantPermissions/StorageGrantBehavior.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2023 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.grantPermissions
+
+import android.Manifest.permission.ACCESS_MEDIA_LOCATION
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+import android.Manifest.permission_group.READ_MEDIA_VISUAL
+import android.Manifest.permission_group.STORAGE
+import android.os.Build
+import com.android.modules.utils.build.SdkLevel
+import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
+import com.android.permissioncontroller.permission.ui.model.DenyButton
+import com.android.permissioncontroller.permission.ui.model.Prompt
+import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptEnabled
+import com.android.permissioncontroller.permission.utils.KotlinUtils.isPhotoPickerPromptSupported
+
+/**
+ * Storage split from one group (STORAGE) into two (READ_MEDIA_VISUAL and READ_MEDIA_AURAL) in T.
+ * There are special dialogs to deal with a pre-T app requesting STORAGE on a post-T device. In U,
+ * the READ_MEDIA_VISUAL group was augmented with the option to select photos, which led to several
+ * new dialogs to handle that.
+ */
+object StorageGrantBehavior : GrantBehavior() {
+ override fun getPrompt(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ isSystemTriggeredPrompt: Boolean
+ ): Prompt {
+ val appSupportsSplitStoragePermissions = appSupportsSplitStoragePermissions(group)
+ if (!SdkLevel.isAtLeastT()) {
+ return Prompt.BASIC
+ } else if (appSupportsSplitStoragePermissions && group.permGroupName == STORAGE) {
+ return Prompt.NO_UI_REJECT_THIS_GROUP
+ }
+
+ if (appSupportsSplitStoragePermissions && !shouldShowPhotoPickerPromptForApp(group)) {
+ return Prompt.BASIC
+ }
+
+ if (!appSupportsSplitStoragePermissions) {
+ if (group.packageInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
+ return Prompt.STORAGE_SUPERGROUP_PRE_Q
+ } else {
+ return Prompt.STORAGE_SUPERGROUP_Q_TO_S
+ }
+ }
+
+ // Else, app supports the new photo picker dialog
+ if (requestedPerms.all { it in getPartialGrantPermissions(group) }) {
+ // Do not allow apps to request only READ_MEDIA_VISUAL_USER_SELECTED
+ return Prompt.NO_UI_REJECT_THIS_GROUP
+ }
+
+ val userSelectedPerm = group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]
+ if (userSelectedPerm?.isUserFixed == true && userSelectedPerm.isGrantedIncludingAppOp) {
+ return Prompt.NO_UI_PHOTO_PICKER_REDIRECT
+ }
+
+ if (userSelectedPerm?.isGrantedIncludingAppOp == true) {
+ return Prompt.SELECT_MORE_PHOTOS
+ } else {
+ return Prompt.SELECT_PHOTOS
+ }
+ }
+
+ override fun getDenyButton(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>,
+ prompt: Prompt
+ ): DenyButton {
+ if (prompt == Prompt.SELECT_MORE_PHOTOS) {
+ return DenyButton.DONT_SELECT_MORE
+ }
+ return BasicGrantBehavior.getDenyButton(group, requestedPerms, prompt)
+ }
+
+ override fun isGroupFullyGranted(
+ group: LightAppPermGroup,
+ requestedPerms: Set<String>
+ ): Boolean {
+ if (!isPhotoPickerPromptSupported() ||
+ group.permGroupName != READ_MEDIA_VISUAL) {
+ return super.isGroupFullyGranted(group, requestedPerms)
+ }
+
+ return group.permissions.values.any {
+ it.name !in getPartialGrantPermissions(group) && it.isGrantedIncludingAppOp
+ }
+ }
+
+ override fun isPermissionFixed(group: LightAppPermGroup, perm: String): Boolean {
+ val userSelectedPerm = group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]
+ if (userSelectedPerm != null && userSelectedPerm.isGrantedIncludingAppOp &&
+ userSelectedPerm.isUserFixed) {
+ // If the user selected permission is fixed and granted, we immediately show the
+ // photo picker, rather than filtering
+ return false
+ }
+ return super.isPermissionFixed(group, perm)
+ }
+
+ private fun appSupportsSplitStoragePermissions(group: LightAppPermGroup) =
+ SdkLevel.isAtLeastT() && group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU
+
+ private fun shouldShowPhotoPickerPromptForApp(group: LightAppPermGroup) =
+ isPhotoPickerPromptEnabled() && group.permGroupName == READ_MEDIA_VISUAL &&
+ (group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE ||
+ appSupportsPhotoPicker(group))
+
+ private fun appSupportsPhotoPicker(group: LightAppPermGroup) =
+ group.packageInfo.targetSdkVersion >= Build.VERSION_CODES.TIRAMISU &&
+ group.permissions[READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit == false
+
+ private fun getPartialGrantPermissions(group: LightAppPermGroup): Set<String> {
+ return if (appSupportsPhotoPicker(group) && shouldShowPhotoPickerPromptForApp(group)) {
+ setOf(READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION)
+ } else {
+ setOf(READ_MEDIA_VISUAL_USER_SELECTED)
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
index d6efd38a6..e173153db 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/ReviewOngoingUsageViewModel.kt
@@ -51,7 +51,6 @@ import com.android.permissioncontroller.permission.ui.handheld.v31.ReviewOngoing
import com.android.permissioncontroller.permission.ui.handheld.v31.ReviewOngoingUsageFragment.VIDEO_CALL
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.KotlinUtils.shouldShowLocationIndicators
-import com.android.permissioncontroller.permission.utils.KotlinUtils.shouldShowPermissionsDashboard
import com.android.permissioncontroller.permission.utils.Utils
import java.time.Instant
import kotlin.math.max
@@ -103,7 +102,7 @@ class ReviewOngoingUsageViewModel(
*/
private val permGroupUsages = LoadAndFreezeLifeData(state, USAGES_KEY,
PermGroupUsageLiveData(PermissionControllerApplication.get(),
- if (shouldShowPermissionsDashboard() || shouldShowLocationIndicators()) {
+ if (shouldShowLocationIndicators()) {
listOf(CAMERA, LOCATION, MICROPHONE)
} else {
listOf(CAMERA, MICROPHONE)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/AppPermissionsFragmentWear.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/AppPermissionsFragmentWear.java
deleted file mode 100644
index 843514b4a..000000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/AppPermissionsFragmentWear.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
-* Copyright (C) 2015 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.wear;
-
-import android.app.Activity;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.ArraySet;
-import android.util.Log;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.fragment.app.Fragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.SwitchPreference;
-import androidx.wear.ble.view.WearableDialogHelper;
-
-import com.android.permissioncontroller.R;
-import com.android.permissioncontroller.permission.model.AppPermissionGroup;
-import com.android.permissioncontroller.permission.model.AppPermissions;
-import com.android.permissioncontroller.permission.model.Permission;
-import com.android.permissioncontroller.permission.utils.ArrayUtils;
-import com.android.permissioncontroller.permission.utils.LocationUtils;
-import com.android.permissioncontroller.permission.utils.Utils;
-import com.android.permissioncontroller.permission.utils.legacy.LegacySafetyNetLogger;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public final class AppPermissionsFragmentWear extends PreferenceFragmentCompat {
- private static final String LOG_TAG = "AppPermFragWear";
-
- private static final String KEY_NO_PERMISSIONS = "no_permissions";
-
- public static AppPermissionsFragmentWear newInstance(String packageName) {
- return setPackageName(new AppPermissionsFragmentWear(), packageName);
- }
-
- private static <T extends Fragment> T setPackageName(T fragment, String packageName) {
- Bundle arguments = new Bundle();
- arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
- fragment.setArguments(arguments);
- return fragment;
- }
-
- private PackageManager mPackageManager;
- private ArraySet<AppPermissionGroup> mToggledGroups;
- private AppPermissions mAppPermissions;
-
- private boolean mHasConfirmedRevoke;
-
- /**
- * Provides click behavior for disabled preferences.
- */
- private static class PermissionSwitchPreference extends SwitchPreference {
-
- private final Activity mActivity;
-
- public PermissionSwitchPreference(Activity activity) {
- super(activity);
- this.mActivity = activity;
- }
-
- @Override
- protected void performClick(View view) {
- super.performClick(view);
-
- if (!isEnabled()) {
- // If setting the permission is disabled, it must have been locked
- // by the device or profile owner. So get that info and pass it to
- // the support details dialog.
- EnforcedAdmin deviceOrProfileOwner = RestrictedLockUtils.getProfileOrDeviceOwner(
- mActivity, UserHandle.of(UserHandle.myUserId()));
- RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
- mActivity, deviceOrProfileOwner);
- }
- }
- }
-
- @Override
- public void onCreatePreferences(Bundle bundle, String s) {
- // empty
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
- Activity activity = getActivity();
- mPackageManager = activity.getPackageManager();
-
- PackageInfo packageInfo;
-
- try {
- packageInfo = mPackageManager.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
- } catch (PackageManager.NameNotFoundException e) {
- Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e);
- packageInfo = null;
- }
-
- if (packageInfo == null) {
- Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show();
- activity.finish();
- return;
- }
-
- mAppPermissions = new AppPermissions(
- activity, packageInfo, true, () -> getActivity().finish());
-
- addPreferencesFromResource(R.xml.watch_permissions);
- initializePermissionGroupList();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mAppPermissions.refresh();
-
- // Also refresh the UI
- for (final AppPermissionGroup group : mAppPermissions.getPermissionGroups()) {
- if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) {
- for (PermissionInfo perm : getPermissionInfosFromGroup(group)) {
- setPreferenceCheckedIfPresent(perm.name,
- group.areRuntimePermissionsGranted(new String[]{ perm.name }));
- }
- } else {
- setPreferenceCheckedIfPresent(group.getName(), group.areRuntimePermissionsGranted());
- }
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- logAndClearToggledGroups();
- }
-
- private void initializePermissionGroupList() {
- List<AppPermissionGroup> groups = mAppPermissions.getPermissionGroups();
- List<SwitchPreference> nonSystemPreferences = new ArrayList<>();
-
- if (!groups.isEmpty()) {
- getPreferenceScreen().removePreference(findPreference(KEY_NO_PERMISSIONS));
- }
-
- for (final AppPermissionGroup group : groups) {
- if (!Utils.shouldShowPermission(getContext(), group)) {
- continue;
- }
-
- boolean isPlatform = group.getDeclaringPackage().equals(Utils.OS_PKG);
-
- if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())) {
- // If permission is controlled individually, we show all requested permission
- // inside this group.
- for (PermissionInfo perm : getPermissionInfosFromGroup(group)) {
- final SwitchPreference pref = createSwitchPreferenceForPermission(group, perm);
- showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform);
- }
- } else {
- final SwitchPreference pref = createSwitchPreferenceForGroup(group);
- showOrAddToNonSystemPreferences(pref, nonSystemPreferences, isPlatform);
- }
- }
-
- // Now add the non-system settings to the end of the list
- for (SwitchPreference nonSystemPreference : nonSystemPreferences) {
- getPreferenceScreen().addPreference(nonSystemPreference);
- }
- }
-
- private void showOrAddToNonSystemPreferences(SwitchPreference pref,
- List<SwitchPreference> nonSystemPreferences, // Mutate
- boolean isPlatform) {
- // The UI shows System settings first, then non-system settings
- if (isPlatform) {
- getPreferenceScreen().addPreference(pref);
- } else {
- nonSystemPreferences.add(pref);
- }
- }
-
- private SwitchPreference createSwitchPreferenceForPermission(AppPermissionGroup group,
- PermissionInfo perm) {
- final SwitchPreference pref = new PermissionSwitchPreference(getActivity());
- pref.setKey(perm.name);
- pref.setTitle(perm.loadLabel(mPackageManager));
- pref.setChecked(group.areRuntimePermissionsGranted(new String[]{ perm.name }));
- pref.setOnPreferenceChangeListener((p, newVal) -> {
- if((Boolean) newVal) {
- group.grantRuntimePermissions(true, false, new String[]{ perm.name });
-
- if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())
- && group.doesSupportRuntimePermissions()) {
- // We are granting a permission from a group but since this is an
- // individual permission control other permissions in the group may
- // be revoked, hence we need to mark them user fixed to prevent the
- // app from requesting a non-granted permission and it being granted
- // because another permission in the group is granted. This applies
- // only to apps that support runtime permissions.
- String[] revokedPermissionsToFix = null;
- final int permissionCount = group.getPermissions().size();
-
- for (int i = 0; i < permissionCount; i++) {
- Permission current = group.getPermissions().get(i);
- if (!current.isGranted() && !current.isUserFixed()) {
- revokedPermissionsToFix = ArrayUtils.appendString(
- revokedPermissionsToFix, current.getName());
- }
- }
-
- if (revokedPermissionsToFix != null) {
- // If some permissions were not granted then they should be fixed.
- group.revokeRuntimePermissions(true, revokedPermissionsToFix);
- }
- }
- } else {
- final Permission appPerm = getPermissionFromGroup(group, perm.name);
- if (appPerm == null) {
- return false;
- }
-
- final boolean grantedByDefault = appPerm.isGrantedByDefault();
- if (grantedByDefault
- || (!group.doesSupportRuntimePermissions() && !mHasConfirmedRevoke)) {
- showRevocationWarningDialog(
- (dialog, which) -> {
- revokePermissionInGroup(group, perm.name);
- pref.setChecked(false);
- if (!appPerm.isGrantedByDefault()) {
- mHasConfirmedRevoke = true;
- }
- },
- grantedByDefault
- ? R.string.system_warning
- : R.string.old_sdk_deny_warning);
- return false;
- } else {
- revokePermissionInGroup(group, perm.name);
- }
- }
-
- return true;
- });
- return pref;
- }
-
- private void showRevocationWarningDialog(
- DialogInterface.OnClickListener confirmListener,
- int warningMessageId) {
- new WearableDialogHelper.DialogBuilder(getContext())
- .setNegativeIcon(R.drawable.confirm_button)
- .setPositiveIcon(R.drawable.cancel_button)
- .setNegativeButton(R.string.grant_dialog_button_deny_anyway, confirmListener)
- .setPositiveButton(R.string.cancel, null)
- .setMessage(warningMessageId)
- .show();
- }
-
- private static Permission getPermissionFromGroup(AppPermissionGroup group, String permName) {
- final int permissionCount = group.getPermissions().size();
-
- for (int i = 0; i < permissionCount; i++) {
- Permission currentPerm = group.getPermissions().get(i);
- if(currentPerm.getName().equals(permName)) {
- return currentPerm;
- };
- }
-
- if ("user".equals(Build.TYPE)) {
- Log.e(LOG_TAG, String.format("The impossible happens, permission %s is not in group %s.",
- permName, group.getName()));
- return null;
- } else {
- // This is impossible, throw a fatal error in non-user build.
- throw new IllegalArgumentException(
- String.format("Permission %s is not in group %s", permName, group.getName()));
- }
- }
-
- private void revokePermissionInGroup(AppPermissionGroup group, String permName) {
- group.revokeRuntimePermissions(true, new String[]{ permName });
-
- if (Utils.areGroupPermissionsIndividuallyControlled(getContext(), group.getName())
- && group.doesSupportRuntimePermissions()
- && !group.areRuntimePermissionsGranted()) {
- // If we just revoked the last permission we need to clear
- // the user fixed state as now the app should be able to
- // request them at runtime if supported.
- group.revokeRuntimePermissions(false);
- }
- }
-
- private SwitchPreference createSwitchPreferenceForGroup(AppPermissionGroup group) {
- final SwitchPreference pref = new PermissionSwitchPreference(getActivity());
-
- pref.setKey(group.getName());
- pref.setTitle(group.getLabel());
- pref.setChecked(group.areRuntimePermissionsGranted());
-
- if (group.isSystemFixed() || group.isPolicyFixed()) {
- pref.setEnabled(false);
- } else {
- pref.setOnPreferenceChangeListener((p, newVal) -> {
- if (LocationUtils.isLocationGroupAndProvider(getContext(),
- group.getName(), group.getApp().packageName)) {
- LocationUtils.showLocationDialog(
- getContext(), mAppPermissions.getAppLabel());
- return false;
- }
-
- if ((Boolean) newVal) {
- setPermission(group, pref, true);
- } else {
- final boolean grantedByDefault = group.hasGrantedByDefaultPermission();
- if (grantedByDefault
- || (!group.doesSupportRuntimePermissions() && !mHasConfirmedRevoke)) {
- showRevocationWarningDialog(
- (dialog, which) -> {
- setPermission(group, pref, false);
- if (!group.hasGrantedByDefaultPermission()) {
- mHasConfirmedRevoke = true;
- }
- },
- grantedByDefault
- ? R.string.system_warning
- : R.string.old_sdk_deny_warning);
- return false;
- } else {
- setPermission(group, pref, false);
- }
- }
-
- return true;
- });
- }
- return pref;
- }
-
- private void setPermission(AppPermissionGroup group, SwitchPreference pref, boolean grant) {
- if (grant) {
- group.grantRuntimePermissions(true, false);
- } else {
- group.revokeRuntimePermissions(false);
- }
- addToggledGroup(group);
- pref.setChecked(grant);
- }
-
- private void addToggledGroup(AppPermissionGroup group) {
- if (mToggledGroups == null) {
- mToggledGroups = new ArraySet<>();
- }
-
- mToggledGroups.add(group);
- }
-
- private void logAndClearToggledGroups() {
- if (mToggledGroups != null) {
- LegacySafetyNetLogger.logPermissionsToggled(mToggledGroups);
- mToggledGroups = null;
- }
- }
-
- private List<PermissionInfo> getPermissionInfosFromGroup(AppPermissionGroup group) {
- ArrayList<PermissionInfo> permInfos = new ArrayList<>(group.getPermissions().size());
- for(Permission perm : group.getPermissions()) {
- try {
- permInfos.add(mPackageManager.getPermissionInfo(perm.getName(), 0));
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(LOG_TAG, "No permission:" + perm.getName());
- }
- }
- return permInfos;
- }
-
- private void setPreferenceCheckedIfPresent(String preferenceKey, boolean checked) {
- Preference pref = findPreference(preferenceKey);
- if (pref instanceof SwitchPreference) {
- ((SwitchPreference) pref).setChecked(checked);
- }
- }
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/GrantPermissionsWearViewHandler.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/GrantPermissionsWearViewHandler.java
index ccd1ed42e..60e507433 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/GrantPermissionsWearViewHandler.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/GrantPermissionsWearViewHandler.java
@@ -16,62 +16,99 @@
package com.android.permissioncontroller.permission.ui.wear;
-import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.graphics.PixelFormat;
-import android.graphics.drawable.Drawable;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ALWAYS_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_FOREGROUND_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ONE_TIME_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_BOTH_LOCATIONS;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_COARSE_LOCATION_ONLY;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_FINE_LOCATION_ONLY;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.FINE_RADIO_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NEXT_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NEXT_LOCATION_DIALOG;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON;
+import static com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_BUTTON;
+
+import android.app.Activity;
import android.graphics.drawable.Icon;
import android.os.Bundle;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
-import android.util.Log;
+import android.util.SparseIntArray;
import android.view.View;
-import android.view.WindowManager;
-import android.widget.Space;
+import android.view.WindowManager.LayoutParams;
-import androidx.wear.ble.view.AcceptDenyDialog;
-import androidx.wear.ble.view.WearableDialogHelper;
+import androidx.annotation.Nullable;
+import androidx.compose.ui.platform.ComposeView;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler;
+import com.android.permissioncontroller.permission.ui.wear.model.WearGrantPermissionsViewModel;
+import com.android.permissioncontroller.permission.ui.wear.model.WearGrantPermissionsViewModelFactory;
+
+import kotlin.Unit;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
- * Watch-specific view handler for the grant permissions activity.
+ * Wear-specific view handler for the grant permissions activity.
*/
-public final class GrantPermissionsWearViewHandler implements GrantPermissionsViewHandler,
- DialogInterface.OnClickListener {
- private static final String TAG = "GrantPermsWatchViewH";
-
- private static final String WATCH_HANDLER_BUNDLE = "watch_handler_bundle";
- private static final String DIALOG_BUNDLE = "dialog_bundle";
- private static final String GROUP_NAME = "group_name";
- private static final String SHOW_DO_NOT_ASK = "show_do_not_ask";
- private static final String ICON = "icon";
- private static final String MESSAGE = "message";
- private static final String CURRENT_PAGE_TEXT = "current_page_text";
+public class GrantPermissionsWearViewHandler implements GrantPermissionsViewHandler {
+
+ public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME";
+ public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT";
+ public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX";
+ public static final String ARG_GROUP_ICON = "ARG_GROUP_ICON";
+ public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE";
+ private static final String ARG_GROUP_DETAIL_MESSAGE = "ARG_GROUP_DETAIL_MESSAGE";
+ private static final String ARG_DIALOG_BUTTON_VISIBILITIES = "ARG_DIALOG_BUTTON_VISIBILITIES";
+ private static final String ARG_DIALOG_LOCATION_VISIBILITIES =
+ "ARG_DIALOG_LOCATION_VISIBILITIES";
+
+ public static final SparseIntArray BUTTON_RES_ID_TO_NUM = new SparseIntArray();
+ static {
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_button, ALLOW_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_always_button,
+ ALLOW_ALWAYS_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_foreground_only_button,
+ ALLOW_FOREGROUND_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_deny_button, DENY_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_deny_and_dont_ask_again_button,
+ DENY_AND_DONT_ASK_AGAIN_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_allow_one_time_button, ALLOW_ONE_TIME_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_button, NO_UPGRADE_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_and_dont_ask_again_button,
+ NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_one_time_button, NO_UPGRADE_OT_BUTTON);
+ BUTTON_RES_ID_TO_NUM.put(R.id.permission_no_upgrade_one_time_and_dont_ask_again_button,
+ NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON);
+ }
- private final Context mContext;
+ private final Activity mActivity;
private ResultListener mResultListener;
- private Dialog mDialog;
-
+ // Configuration of the current dialog
private String mGroupName;
- private boolean mShowDoNotAsk;
-
- private CharSequence mMessage;
- private String mCurrentPageText;
- private Icon mIcon;
-
- public GrantPermissionsWearViewHandler(Context context) {
- mContext = context;
+ private int mGroupCount;
+ private int mGroupIndex;
+ private Icon mGroupIcon;
+ private CharSequence mGroupMessage;
+ private CharSequence mDetailMessage;
+ private final boolean[] mButtonVisibilities = new boolean[NEXT_BUTTON];
+ private final boolean[] mLocationVisibilities = new boolean[NEXT_LOCATION_DIALOG];
+ // View model to update WearGrantPermissionsScreen elements
+ private WearGrantPermissionsViewModel mViewModel;
+
+ public GrantPermissionsWearViewHandler(Activity activity) {
+ mActivity = activity;
}
@Override
@@ -81,17 +118,30 @@ public final class GrantPermissionsWearViewHandler implements GrantPermissionsVi
}
@Override
- public View createView() {
- return new Space(mContext);
+ public void saveInstanceState(Bundle arguments) {
+ arguments.putString(ARG_GROUP_NAME, mGroupName);
+ arguments.putInt(ARG_GROUP_COUNT, mGroupCount);
+ arguments.putInt(ARG_GROUP_INDEX, mGroupIndex);
+ arguments.putParcelable(ARG_GROUP_ICON, mGroupIcon);
+ arguments.putCharSequence(ARG_GROUP_MESSAGE, mGroupMessage);
+ arguments.putCharSequence(ARG_GROUP_DETAIL_MESSAGE, mDetailMessage);
+ arguments.putBooleanArray(ARG_DIALOG_BUTTON_VISIBILITIES, mButtonVisibilities);
+ arguments.putBooleanArray(ARG_DIALOG_LOCATION_VISIBILITIES, mLocationVisibilities);
}
@Override
- public void updateWindowAttributes(WindowManager.LayoutParams outLayoutParams) {
- outLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
- outLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
- outLayoutParams.format = PixelFormat.OPAQUE;
- outLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
- outLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ public void loadInstanceState(Bundle savedInstanceState) {
+ mGroupName = savedInstanceState.getString(ARG_GROUP_NAME);
+ mGroupMessage = savedInstanceState.getCharSequence(ARG_GROUP_MESSAGE);
+ mGroupIcon = savedInstanceState.getParcelable(ARG_GROUP_ICON);
+ mGroupCount = savedInstanceState.getInt(ARG_GROUP_COUNT);
+ mGroupIndex = savedInstanceState.getInt(ARG_GROUP_INDEX);
+ mDetailMessage = savedInstanceState.getCharSequence(ARG_GROUP_DETAIL_MESSAGE);
+ setButtonVisibilities(savedInstanceState.getBooleanArray(ARG_DIALOG_BUTTON_VISIBILITIES));
+ setLocationVisibilities(
+ savedInstanceState.getBooleanArray(ARG_DIALOG_LOCATION_VISIBILITIES));
+
+ updateScreen();
}
@Override
@@ -100,140 +150,167 @@ public final class GrantPermissionsWearViewHandler implements GrantPermissionsVi
CharSequence permissionRationaleMessage, boolean[] buttonVisibilities,
boolean[] locationVisibilities) {
// permissionRationaleMessage ignored by wear
-
- // TODO: Handle detailMessage
-
- boolean showDoNotAsk = buttonVisibilities[DENY_AND_DONT_ASK_AGAIN_BUTTON];
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "updateUi() - groupName: " + groupName
- + ", groupCount: " + groupCount
- + ", groupIndex: " + groupIndex
- + ", icon: " + icon
- + ", message: " + message
- + ", showDoNotAsk: " + showDoNotAsk);
+ if (mActivity.isFinishing()) {
+ return;
}
-
mGroupName = groupName;
- mShowDoNotAsk = showDoNotAsk;
- mMessage = message;
- mIcon = icon;
- mCurrentPageText = groupCount > 1
- ? mContext.getString(R.string.current_permission_template,
- groupIndex + 1, groupCount)
- : null;
- showDialog(null);
+ mGroupCount = groupCount;
+ mGroupIndex = groupIndex;
+ mGroupIcon = icon;
+ mGroupMessage = message;
+ mDetailMessage = detailMessage;
+ setButtonVisibilities(buttonVisibilities);
+ setLocationVisibilities(locationVisibilities);
+
+ updateScreen();
}
- private void showDialog(Bundle savedInstanceState) {
- TypedArray a = mContext.obtainStyledAttributes(
- new int[] { android.R.attr.textColorPrimary });
- int color = a.getColor(0, mContext.getColor(android.R.color.white));
- a.recycle();
- Drawable drawable = mIcon == null ? null : mIcon.setTint(color).loadDrawable(mContext);
-
- SpannableStringBuilder ssb = new SpannableStringBuilder();
- if (!TextUtils.isEmpty(mCurrentPageText)) {
- ssb.append(mCurrentPageText, new TextAppearanceSpan(mContext, R.style.BreadcrumbText),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- ssb.append('\n');
+ private void updateScreen() {
+ mViewModel.getIconLiveData().setValue(
+ mGroupIcon == null ? null : mGroupIcon.loadDrawable(mActivity));
+ mViewModel.getGroupMessageLiveData().setValue(mGroupMessage.toString());
+ mViewModel.getDetailMessageLiveData().setValue(
+ mDetailMessage == null ? null : mDetailMessage.toString());
+ int numButtons = BUTTON_RES_ID_TO_NUM.size();
+ List<Boolean> buttonVisibilityList = Arrays.asList(new Boolean[NEXT_BUTTON]);
+ for (int i = 0; i < numButtons; i++) {
+ int pos = BUTTON_RES_ID_TO_NUM.valueAt(i);
+ buttonVisibilityList.set(pos, mButtonVisibilities[pos] ? Boolean.TRUE : Boolean.FALSE);
}
- if (!TextUtils.isEmpty(mMessage)) {
- ssb.append(mMessage, new TextAppearanceSpan(mContext, R.style.TitleText),
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ mViewModel.getButtonVisibilitiesLiveData().setValue(buttonVisibilityList);
+ List<Boolean> locationVisibilityList = Arrays.asList(new Boolean[NEXT_LOCATION_DIALOG]);
+ for (int i = 0; i < locationVisibilityList.size(); i++) {
+ locationVisibilityList.set(i, mLocationVisibilities[i] ? Boolean.TRUE : Boolean.FALSE);
}
-
- if (mDialog != null) {
- mDialog.dismiss();
- mDialog = null;
+ mViewModel.getLocationVisibilitiesLiveData().setValue(locationVisibilityList);
+ if (mLocationVisibilities[DIALOG_WITH_BOTH_LOCATIONS]) {
+ mViewModel.getPreciseLocationCheckedLiveData()
+ .setValue(mLocationVisibilities[FINE_RADIO_BUTTON]);
+ } else if (mLocationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]
+ || mLocationVisibilities[DIALOG_WITH_COARSE_LOCATION_ONLY]) {
+ mViewModel.getPreciseLocationCheckedLiveData().setValue(false);
}
+ }
- if (mShowDoNotAsk) {
- AlertDialog alertDialog = new WearableDialogHelper.DialogBuilder(mContext)
- .setPositiveIcon(R.drawable.confirm_button)
- .setNeutralIcon(R.drawable.cancel_button)
- .setNegativeIcon(R.drawable.deny_button)
- .setTitle(ssb)
- .setIcon(drawable)
- .setPositiveButton(R.string.grant_dialog_button_allow, this)
- .setNeutralButton(R.string.grant_dialog_button_deny, this)
- .setNegativeButton(R.string.grant_dialog_button_deny_dont_ask_again, this)
- .show();
- alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
- .setId(R.id.permission_allow_button);
- alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL)
- .setId(R.id.permission_deny_button);
- alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
- .setId(R.id.permission_deny_dont_ask_again_button);
-
- mDialog = alertDialog;
- } else {
- AcceptDenyDialog acceptDenyDialog = new AcceptDenyDialog(mContext);
- acceptDenyDialog.setTitle(ssb);
- acceptDenyDialog.setIcon(drawable);
- acceptDenyDialog.setPositiveButton(this);
- acceptDenyDialog.setNegativeButton(this);
- acceptDenyDialog.show();
- acceptDenyDialog.getButton(DialogInterface.BUTTON_POSITIVE)
- .setId(R.id.permission_allow_button);
- acceptDenyDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
- .setId(R.id.permission_deny_button);
-
- mDialog = acceptDenyDialog;
+ private void onLocationSwitchChanged(boolean checked) {
+ mViewModel.getPreciseLocationCheckedLiveData().setValue(checked);
+ }
+
+ private void onButtonClicked(int id) {
+ List<String> affectedForegroundPermissions = null;
+ if (mLocationVisibilities[DIALOG_WITH_BOTH_LOCATIONS]) {
+ if (Boolean.TRUE.equals(mViewModel.getPreciseLocationCheckedLiveData().getValue())) {
+ affectedForegroundPermissions = Arrays.asList(
+ ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION);
+ } else {
+ affectedForegroundPermissions = Collections.singletonList(ACCESS_COARSE_LOCATION);
+ }
+ } else if (mLocationVisibilities[DIALOG_WITH_FINE_LOCATION_ONLY]) {
+ affectedForegroundPermissions = Collections.singletonList(ACCESS_FINE_LOCATION);
+ } else if (mLocationVisibilities[DIALOG_WITH_COARSE_LOCATION_ONLY]) {
+ affectedForegroundPermissions = Collections.singletonList(ACCESS_COARSE_LOCATION);
}
- mDialog.setCancelable(false);
- if (savedInstanceState != null) {
- mDialog.onRestoreInstanceState(savedInstanceState);
+ int button = -1;
+ try {
+ button = BUTTON_RES_ID_TO_NUM.get(id);
+ } catch (NullPointerException e) {
+ // Clicked a view which is not one of the defined buttons
+ return;
+ }
+ // TODO (b/297534305): Research on performAccessibilityAction().
+ switch (button) {
+ case ALLOW_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, GRANTED_ALWAYS);
+ }
+ break;
+ case ALLOW_FOREGROUND_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, GRANTED_FOREGROUND_ONLY);
+ }
+ break;
+ case ALLOW_ALWAYS_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, GRANTED_ALWAYS);
+ }
+ break;
+ case ALLOW_ONE_TIME_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, GRANTED_ONE_TIME);
+ }
+ break;
+ case DENY_BUTTON:
+ case NO_UPGRADE_BUTTON:
+ case NO_UPGRADE_OT_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, DENIED);
+ }
+ break;
+ case DENY_AND_DONT_ASK_AGAIN_BUTTON:
+ case NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON:
+ case NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON:
+ if (mResultListener != null) {
+ mResultListener.onPermissionGrantResult(mGroupName,
+ affectedForegroundPermissions, DENIED_DO_NOT_ASK_AGAIN);
+ }
+ break;
}
}
@Override
- public void saveInstanceState(Bundle outState) {
- Bundle b = new Bundle();
- b.putByte(SHOW_DO_NOT_ASK, (byte) (mShowDoNotAsk ? 1 : 0));
- b.putString(GROUP_NAME, mGroupName);
- b.putBundle(DIALOG_BUNDLE, mDialog.onSaveInstanceState());
+ public View createView() {
+ WearGrantPermissionsViewModelFactory factory = new WearGrantPermissionsViewModelFactory();
+ mViewModel = factory.create(WearGrantPermissionsViewModel.class);
+ ComposeView root = new ComposeView(mActivity);
+
+ WearGrantPermissionsScreenKt.setContent(root,
+ mViewModel,
+ id -> {
+ onButtonClicked(id);
+ return Unit.INSTANCE;
+ },
+ checked -> {
+ onLocationSwitchChanged(checked);
+ return Unit.INSTANCE;
+ });
+ if (mGroupName != null) {
+ updateScreen();
+ }
- outState.putBundle(WATCH_HANDLER_BUNDLE, b);
+ return root;
}
@Override
- public void loadInstanceState(Bundle savedInstanceState) {
- Bundle b = savedInstanceState.getBundle(WATCH_HANDLER_BUNDLE);
- mShowDoNotAsk = b.getByte(SHOW_DO_NOT_ASK) == 1;
- mGroupName = b.getString(GROUP_NAME);
- showDialog(b.getBundle(DIALOG_BUNDLE));
+ public void updateWindowAttributes(LayoutParams outLayoutParams) {
+ // No-op
}
- @Override
- public void onBackPressed() {
- notifyListener(DENIED);
+ private void setButtonVisibilities(@Nullable boolean[] visibilities) {
+ for (int i = 0; i < mButtonVisibilities.length; i++) {
+ mButtonVisibilities[i] =
+ visibilities != null && i < visibilities.length && visibilities[i];
+ }
}
- @Override
- public void onClick(DialogInterface dialog, int which) {
- switch (which) {
- case DialogInterface.BUTTON_POSITIVE:
- notifyListener(GRANTED_ALWAYS);
- break;
- case DialogInterface.BUTTON_NEUTRAL:
- notifyListener(DENIED);
- break;
- case DialogInterface.BUTTON_NEGATIVE:
- /* In AlertDialog, the negative button is also a don't ask again button. */
- if (dialog instanceof AlertDialog) {
- notifyListener(DENIED_DO_NOT_ASK_AGAIN);
- } else {
- notifyListener(DENIED);
- }
- break;
+ private void setLocationVisibilities(@Nullable boolean[] visibilities) {
+ for (int i = 0; i < mLocationVisibilities.length; i++) {
+ mLocationVisibilities[i] =
+ visibilities != null && i < visibilities.length && visibilities[i];
}
}
- private void notifyListener(@Result int result) {
+ @Override
+ public void onBackPressed() {
if (mResultListener != null) {
- mResultListener.onPermissionGrantResult(mGroupName, result);
+ mResultListener.onPermissionGrantResult(mGroupName, CANCELED);
+ } else {
+ mActivity.finish();
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/ReviewPermissionsWearFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/ReviewPermissionsWearFragment.java
index c31aa5d63..9965a6b38 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/ReviewPermissionsWearFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/ReviewPermissionsWearFragment.java
@@ -43,8 +43,8 @@ import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.AppPermissions;
import com.android.permissioncontroller.permission.utils.Utils;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
public class ReviewPermissionsWearFragment extends PreferenceFragmentCompat
implements Preference.OnPreferenceChangeListener {
@@ -290,7 +290,7 @@ public class ReviewPermissionsWearFragment extends PreferenceFragmentCompat
titlePref.setIcon(icon);
// Set message
- String appLabel = mAppPermissions.getAppLabel().toString();
+ String appLabel = Html.escapeHtml(mAppPermissions.getAppLabel().toString());
final int labelTemplateResId = isPackageUpdated()
? R.string.permission_review_title_template_update
: R.string.permission_review_title_template_install;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt
new file mode 100644
index 000000000..ad171fc2c
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.Manifest
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.StringRes
+import androidx.compose.ui.platform.ComposeView
+import androidx.core.os.BundleCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__GRANT_FINE_LOCATION
+import com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__REVOKE_FINE_LOCATION
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.DENIED_DO_NOT_ASK_AGAIN
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_ALWAYS
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.GRANTED_FOREGROUND_ONLY
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler
+import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
+import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_CALLER_NAME
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ChangeRequest
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ConfirmDialogShowingFragment
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModelFactory
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModelFactory
+import com.android.permissioncontroller.permission.ui.wear.model.ConfirmDialogArgs
+import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
+import com.android.settingslib.RestrictedLockUtils
+
+/**
+ * Show and manage a single permission group for an app.
+ *
+ * <p>Allows the user to control whether the app is granted the permission
+ * <p>
+ * Based on AppPermissionFragment in handheld code.
+ */
+class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment {
+
+ private lateinit var confirmDialogViewModel: AppPermissionConfirmDialogViewModel
+
+ companion object {
+ private const val GRANT_CATEGORY = "grant_category"
+
+ /**
+ * Create a bundle with the arguments needed by this fragment
+ *
+ * @param packageName The name of the package
+ * @param permName The name of the permission whose group this fragment is for (optional)
+ * @param groupName The name of the permission group (required if permName not specified)
+ * @param userHandle The user of the app permission group
+ * @param caller The name of the fragment we called from
+ * @param sessionId The current session ID
+ * @param grantCategory The grant status of this app permission group. Used to initially set the
+ * button state
+ * @return A bundle with all of the args placed
+ */
+ @JvmStatic
+ fun createArgs(
+ packageName: String?,
+ permName: String?,
+ groupName: String?,
+ userHandle: UserHandle?,
+ caller: String?,
+ sessionId: Long,
+ grantCategory: String?
+ ): Bundle {
+ val arguments = Bundle()
+ arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName)
+ if (groupName == null) {
+ arguments.putString(Intent.EXTRA_PERMISSION_NAME, permName)
+ } else {
+ arguments.putString(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName)
+ }
+ arguments.putParcelable(Intent.EXTRA_USER, userHandle)
+ arguments.putString(EXTRA_CALLER_NAME, caller)
+ arguments.putLong(EXTRA_SESSION_ID, sessionId)
+ arguments.putString(GRANT_CATEGORY, grantCategory)
+ return arguments
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val activity = requireActivity()
+ val packageName = arguments?.getString(Intent.EXTRA_PACKAGE_NAME)
+ ?: throw RuntimeException("Package name must not be null.")
+ val permGroupName = arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME)
+ ?: arguments?.getString(Intent.EXTRA_PERMISSION_NAME)
+ ?: throw RuntimeException("Permission name must not be null.")
+
+ val isStorageGroup = permGroupName == Manifest.permission_group.STORAGE
+
+ val user = arguments?.let{
+ BundleCompat.getParcelable(it, Intent.EXTRA_USER, UserHandle::class.java)
+ } ?: UserHandle.SYSTEM
+ val permGroupLabel = getPermGroupLabel(
+ activity,
+ permGroupName
+ ).toString()
+
+ val sessionId = arguments?.getLong(EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
+
+ val factory = AppPermissionViewModelFactory(
+ activity.getApplication(),
+ packageName,
+ permGroupName,
+ user,
+ sessionId
+ )
+ val viewModel = ViewModelProvider(this, factory).get(
+ AppPermissionViewModel::class.java
+ )
+ confirmDialogViewModel =
+ ViewModelProvider(this, AppPermissionConfirmDialogViewModelFactory()).get(
+ AppPermissionConfirmDialogViewModel::class.java
+ )
+
+ val onLocationSwitchChanged: (Boolean) -> Unit = { checked ->
+ run {
+ val changeRequest = if (checked) {
+ ChangeRequest.GRANT_FINE_LOCATION
+ } else {
+ ChangeRequest.REVOKE_FINE_LOCATION
+ }
+ val buttonClicked = if (checked) {
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__GRANT_FINE_LOCATION
+ } else {
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__REVOKE_FINE_LOCATION
+ }
+ viewModel.requestChange(false, this, this, changeRequest, buttonClicked)
+ }
+ }
+ val onGrantedStateChanged: (ButtonType, Boolean) -> Unit = { buttonType, checked ->
+ run {
+ if (!checked) {
+ return@run
+ }
+ val param = getGrantedStateChangeParam(buttonType)
+ if (!isStorageGroup || !param.requiresCustomStorageBehavior) {
+ viewModel.requestChange(
+ param.setOneTime,
+ this,
+ this,
+ param.request,
+ param.buttonClickAction
+ )
+ } else {
+ showConfirmDialog(
+ ChangeRequest.GRANT_All_FILE_ACCESS,
+ R.string.special_file_access_dialog,
+ -1,
+ false
+ )
+ }
+ setResult(param.result, permGroupName)
+ }
+ }
+ val onFooterClicked: (RestrictedLockUtils.EnforcedAdmin) -> Unit = { admin ->
+ run {
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(requireContext(), admin)
+ }
+ }
+ val onConfirmDialogOkButtonClick: (ConfirmDialogArgs) -> Unit =
+ { args ->
+ run {
+ if (args.changeRequest == ChangeRequest.GRANT_All_FILE_ACCESS) {
+ viewModel.setAllFilesAccess(true)
+ viewModel.requestChange(
+ false,
+ this,
+ this,
+ ChangeRequest.GRANT_BOTH,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW
+ )
+ } else {
+ viewModel.onDenyAnyWay(args.changeRequest, args.buttonPressed, args.oneTime)
+ }
+ confirmDialogViewModel.showConfirmDialogLiveData.value = false
+ }
+ }
+ val onConfirmDialogCancelButtonClick: () -> Unit = {
+ confirmDialogViewModel.showConfirmDialogLiveData.value = false
+ }
+ val onAdvancedConfirmDialogOkButtonClick: (AdvancedConfirmDialogArgs) -> Unit =
+ { args ->
+ run {
+ viewModel.requestChange(
+ args.setOneTime!!,
+ this,
+ this,
+ args.changeRequest!!,
+ args.buttonClicked!!
+ )
+ confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = false
+ }
+ }
+ val onAdvancedConfirmDialogCancelButtonClick: () -> Unit = {
+ confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = false
+ }
+
+ return ComposeView(activity).apply {
+ setContent {
+ WearAppPermissionScreen(
+ permGroupLabel,
+ viewModel,
+ confirmDialogViewModel,
+ onLocationSwitchChanged,
+ onGrantedStateChanged,
+ onFooterClicked,
+ onConfirmDialogOkButtonClick,
+ onConfirmDialogCancelButtonClick,
+ onAdvancedConfirmDialogOkButtonClick,
+ onAdvancedConfirmDialogCancelButtonClick
+ )
+ }
+ }
+ }
+
+ override fun showConfirmDialog(
+ changeRequest: ChangeRequest,
+ @StringRes messageId: Int,
+ buttonPressed: Int,
+ oneTime: Boolean
+ ) {
+ confirmDialogViewModel.confirmDialogArgs = ConfirmDialogArgs(
+ messageId = messageId,
+ changeRequest = changeRequest,
+ buttonPressed = buttonPressed,
+ oneTime = oneTime
+ )
+ confirmDialogViewModel.showConfirmDialogLiveData.value = true
+ }
+
+ override fun showAdvancedConfirmDialog(args: AdvancedConfirmDialogArgs) {
+ confirmDialogViewModel.advancedConfirmDialogArgs = args
+ confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = true
+ }
+
+ private fun setResult(@GrantPermissionsViewHandler.Result result: Int, permGroupName: String) {
+ val intent: Intent = Intent()
+ .putExtra(ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED, permGroupName)
+ .putExtra(ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT, result)
+ requireActivity().setResult(Activity.RESULT_OK, intent)
+ }
+
+ fun getGrantedStateChangeParam(buttonType: ButtonType) = when (buttonType) {
+ ButtonType.ALLOW -> GrantedStateChangeParam(
+ false,
+ ChangeRequest.GRANT_FOREGROUND,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW,
+ GRANTED_ALWAYS,
+ false
+ )
+
+ ButtonType.ALLOW_ALWAYS -> GrantedStateChangeParam(
+ false,
+ ChangeRequest.GRANT_BOTH,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS,
+ GRANTED_ALWAYS,
+ true
+ )
+
+ ButtonType.ALLOW_FOREGROUND -> GrantedStateChangeParam(
+ false,
+ ChangeRequest.GRANT_FOREGROUND_ONLY,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND,
+ GRANTED_FOREGROUND_ONLY,
+ true
+ )
+
+ ButtonType.ASK -> GrantedStateChangeParam(
+ true,
+ ChangeRequest.REVOKE_BOTH,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME,
+ DENIED,
+ false
+ )
+
+ ButtonType.DENY -> GrantedStateChangeParam(
+ false,
+ ChangeRequest.REVOKE_BOTH,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY,
+ DENIED_DO_NOT_ASK_AGAIN,
+ false
+ )
+
+ ButtonType.DENY_FOREGROUND -> GrantedStateChangeParam(
+ false,
+ ChangeRequest.REVOKE_FOREGROUND,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND,
+ DENIED_DO_NOT_ASK_AGAIN,
+ false
+ )
+
+ else -> throw RuntimeException("Wrong button type: $buttonType")
+ }
+}
+
+data class GrantedStateChangeParam(
+ val setOneTime: Boolean,
+ val request: ChangeRequest,
+ val buttonClickAction: Int,
+ val result: Int,
+ val requiresCustomStorageBehavior: Boolean
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt
new file mode 100644
index 000000000..cf48805dc
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.os.UserHandle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.compose.ui.platform.ComposeView
+import androidx.core.os.BundleCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.model.AppPermissions
+import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel
+import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModelFactory
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModelFactory
+
+
+class WearAppPermissionGroupsFragment : Fragment() {
+ private lateinit var helper: WearAppPermissionGroupsHelper
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val packageName = arguments?.getString(Intent.EXTRA_PACKAGE_NAME) ?: ""
+ val user = arguments?.let {
+ BundleCompat.getParcelable(it, Intent.EXTRA_USER, UserHandle::class.java)!!
+ } ?: UserHandle.SYSTEM
+
+ val activity: Activity = requireActivity()
+ val packageManager = activity.packageManager
+
+ val packageInfo: PackageInfo? = try {
+ packageManager.getPackageInfo(
+ packageName,
+ PackageManager.GET_PERMISSIONS
+ )
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e)
+ null
+ }
+
+ if (packageInfo == null) {
+ Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show()
+ activity.finish()
+ return null
+ }
+ val sessionId = arguments?.getLong(EXTRA_SESSION_ID, 0) ?: 0
+ val appPermissions = AppPermissions(activity, packageInfo, true, { activity.finish() })
+ val factory = AppPermissionGroupsViewModelFactory(
+ packageName,
+ user,
+ sessionId
+ )
+ val viewModel =
+ ViewModelProvider(this, factory).get(AppPermissionGroupsViewModel::class.java)
+ val revokeDialogViewModel =
+ ViewModelProvider(this, AppPermissionGroupsRevokeDialogViewModelFactory()).get(
+ AppPermissionGroupsRevokeDialogViewModel::class.java
+ )
+ helper = WearAppPermissionGroupsHelper(
+ context = requireContext(),
+ fragment = this,
+ user = user,
+ sessionId = sessionId,
+ appPermissions = appPermissions,
+ viewModel = viewModel,
+ revokeDialogViewModel = revokeDialogViewModel
+ )
+
+ return ComposeView(activity).apply {
+ setContent {
+ WearAppPermissionGroupsScreen(
+ helper
+ )
+ }
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ helper.logAndClearToggledGroups()
+ }
+
+ companion object {
+ const val LOG_TAG = "WearAppPermissionGroups"
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt
new file mode 100644
index 000000000..a2b4ffa87
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsHelper.kt
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.PermissionInfo
+import android.os.Build
+import android.os.UserHandle
+import android.util.ArraySet
+import android.util.Log
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.hibernation.isHibernationEnabled
+import com.android.permissioncontroller.permission.model.AppPermissionGroup
+import com.android.permissioncontroller.permission.model.AppPermissions
+import com.android.permissioncontroller.permission.model.Permission
+import com.android.permissioncontroller.permission.model.livedatatypes.HibernationSettingState
+import com.android.permissioncontroller.permission.ui.Category
+import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog
+import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment
+import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel
+import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel.GroupUiInfo
+import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel.PermSubtitle
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionGroupsRevokeDialogViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs
+import com.android.permissioncontroller.permission.utils.ArrayUtils
+import com.android.permissioncontroller.permission.utils.LocationUtils
+import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.permission.utils.legacy.LegacySafetyNetLogger
+import com.android.permissioncontroller.permission.utils.navigateSafe
+
+class WearAppPermissionGroupsHelper(
+ val context: Context,
+ val fragment: Fragment,
+ val user: UserHandle,
+ val sessionId: Long,
+ private val appPermissions: AppPermissions,
+ val viewModel: AppPermissionGroupsViewModel,
+ val revokeDialogViewModel: AppPermissionGroupsRevokeDialogViewModel,
+ private val toggledGroups: ArraySet<AppPermissionGroup> = ArraySet()
+) {
+ fun getPermissionGroupChipParams(): List<PermissionGroupChipParam> {
+ if (DEBUG) {
+ Log.d(TAG, "getPermissionGroupChipParams() called")
+ }
+ val groupUiInfos = viewModel.packagePermGroupsLiveData.value
+ val groups: List<AppPermissionGroup> = appPermissions.permissionGroups
+
+ val grantedTypes: MutableMap<String, Category> = HashMap()
+ val bookKeeping: MutableMap<String, GroupUiInfo> = HashMap()
+ if (groupUiInfos != null) {
+ for (category in groupUiInfos.keys) {
+ val groupInfoList: List<GroupUiInfo> = groupUiInfos[category] ?: emptyList()
+ for (groupInfo in groupInfoList) {
+ bookKeeping[groupInfo.groupName] = groupInfo
+ grantedTypes[groupInfo.groupName] = category
+ }
+ }
+ }
+
+ val list: MutableList<PermissionGroupChipParam> = ArrayList()
+
+ groups.filter { Utils.shouldShowPermission(context, it) }
+ .partition { it.declaringPackage == Utils.OS_PKG }
+ .let { it.first.plus(it.second) }.forEach { group ->
+ if (Utils.areGroupPermissionsIndividuallyControlled(context, group.name)) {
+ // If permission is controlled individually, we show all requested permission
+ // inside this group.
+ for (perm in getPermissionInfosFromGroup(group)) {
+ list.add(PermissionGroupChipParam(
+ group = group,
+ perm = perm,
+ label = perm.loadLabel(context.packageManager).toString(),
+ checked = group.areRuntimePermissionsGranted(arrayOf(perm.name)),
+ onCheckedChanged = { checked ->
+ run {
+ onPermissionGrantedStateChanged(group, perm, checked)
+ }
+ }
+ ))
+ }
+ } else {
+ val category = grantedTypes[group.name]
+ if (category != null) {
+ list.add(
+ PermissionGroupChipParam(
+ group = group,
+ label = group.label.toString(),
+ summary = bookKeeping[group.name]?.let {
+ getSummary(category, it.subtitle)
+ },
+ onClick = {
+ onPermissionGroupClicked(group, category.categoryName)
+ }
+ )
+ )
+ }
+ }
+ }
+ return list
+ }
+
+ private fun getSummary(
+ category: Category?,
+ subtitle: PermSubtitle
+ ): Int? {
+ if (category != null) {
+ when (category) {
+ Category.ALLOWED -> return R.string.allowed_header
+ Category.ASK -> return R.string.ask_header
+ Category.DENIED -> return R.string.denied_header
+ else -> { /* Fallback though */ }
+ }
+ }
+ return when (subtitle) {
+ PermSubtitle.FOREGROUND_ONLY -> R.string.permission_subtitle_only_in_foreground
+ PermSubtitle.MEDIA_ONLY -> R.string.permission_subtitle_media_only
+ PermSubtitle.ALL_FILES -> R.string.permission_subtitle_all_files
+ else -> null
+ }
+ }
+
+ private fun getPermissionInfosFromGroup(group: AppPermissionGroup): List<PermissionInfo> =
+ group.permissions.map {
+ it?.let {
+ try {
+ context.packageManager.getPermissionInfo(it.name, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Log.w(TAG, "No permission:" + it.name)
+ null
+ }
+ }
+ }.filterNotNull().toList()
+
+ private fun onPermissionGrantedStateChanged(
+ group: AppPermissionGroup,
+ perm: PermissionInfo,
+ checked: Boolean
+ ) {
+ if (checked) {
+ group.grantRuntimePermissions(true, false, arrayOf(perm.name))
+
+ if (Utils.areGroupPermissionsIndividuallyControlled(context, group.name) &&
+ group.doesSupportRuntimePermissions()
+ ) {
+ // We are granting a permission from a group but since this is an
+ // individual permission control other permissions in the group may
+ // be revoked, hence we need to mark them user fixed to prevent the
+ // app from requesting a non-granted permission and it being granted
+ // because another permission in the group is granted. This applies
+ // only to apps that support runtime permissions.
+ var revokedPermissionsToFix: Array<String?>? = null
+ val permissionCount = group.permissions.size
+ for (i in 0 until permissionCount) {
+ val current = group.permissions[i]
+ if (!current.isGranted && !current.isUserFixed) {
+ revokedPermissionsToFix = ArrayUtils.appendString(
+ revokedPermissionsToFix, current.name
+ )
+ }
+ }
+ if (revokedPermissionsToFix != null) {
+ // If some permissions were not granted then they should be fixed.
+ group.revokeRuntimePermissions(true, revokedPermissionsToFix)
+ }
+ }
+ } else {
+ val appPerm: Permission = getPermissionFromGroup(group, perm.name) ?: return
+
+ val grantedByDefault = appPerm.isGrantedByDefault
+ if (grantedByDefault ||
+ (!group.doesSupportRuntimePermissions() &&
+ !revokeDialogViewModel.hasConfirmedRevoke)) {
+ showRevocationWarningDialog(
+ messageId = if (grantedByDefault) {
+ R.string.system_warning
+ } else {
+ R.string.old_sdk_deny_warning
+ },
+ onOkButtonClick = {
+ revokePermissionInGroup(group, perm.name)
+ if (!appPerm.isGrantedByDefault) {
+ revokeDialogViewModel.hasConfirmedRevoke = true
+ }
+ revokeDialogViewModel.dismissDialog()
+ }
+ )
+ } else {
+ revokePermissionInGroup(group, perm.name)
+ }
+ }
+ }
+
+ private fun getPermissionFromGroup(group: AppPermissionGroup, permName: String): Permission? {
+ return group.permissions.find { it.name == permName } ?: let{
+ if ("user" == Build.TYPE) {
+ Log.e(TAG,
+ "The impossible happens, permission $permName is not in group $group.name.")
+ null
+ } else {
+ // This is impossible, throw a fatal error in non-user build.
+ throw IllegalArgumentException("Permission $permName is not in group $group.name%s")
+ }
+ }
+ }
+
+ private fun revokePermissionInGroup(group: AppPermissionGroup, permName: String) {
+ group.revokeRuntimePermissions(true, arrayOf(permName))
+
+ if (Utils.areGroupPermissionsIndividuallyControlled(context, group.name) &&
+ group.doesSupportRuntimePermissions() &&
+ !group.areRuntimePermissionsGranted()
+ ) {
+ // If we just revoked the last permission we need to clear
+ // the user fixed state as now the app should be able to
+ // request them at runtime if supported.
+ group.revokeRuntimePermissions(false)
+ }
+ }
+
+ private fun showRevocationWarningDialog(
+ messageId: Int,
+ onOkButtonClick: () -> Unit,
+ onCancelButtonClick: () -> Unit = { revokeDialogViewModel.dismissDialog() }
+ ) {
+ revokeDialogViewModel.revokeDialogArgs = RevokeDialogArgs(
+ messageId = messageId,
+ onOkButtonClick = onOkButtonClick,
+ onCancelButtonClick = onCancelButtonClick
+ )
+ revokeDialogViewModel.showDialogLiveData.value = true
+ }
+
+ private fun onPermissionGroupClicked(group: AppPermissionGroup, grantCategory: String) {
+ val permGroupName = group.name
+ val packageName = group.app?.packageName ?: ""
+ val caller = WearAppPermissionGroupsFragment::class.java.name
+
+ addToggledGroup(group)
+
+ if (LocationUtils.isLocationGroupAndProvider(context, permGroupName, packageName)) {
+ val intent = Intent(
+ context,
+ LocationProviderInterceptDialog::class.java
+ )
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
+ context.startActivityAsUser(intent, user)
+ } else if (LocationUtils.isLocationGroupAndControllerExtraPackage(
+ context,
+ permGroupName,
+ packageName
+ )
+ ) {
+ // Redirect to location controller extra package settings.
+ LocationUtils.startLocationControllerExtraPackageSettings(context, user)
+ } else {
+ val args = AppPermissionFragment.createArgs(
+ packageName,
+ null,
+ permGroupName,
+ user,
+ caller,
+ sessionId,
+ grantCategory
+ )
+ fragment.findNavController().navigateSafe(R.id.perm_groups_to_app, args)
+ }
+ }
+
+ private fun addToggledGroup(group: AppPermissionGroup) {
+ toggledGroups.add(group)
+ }
+
+ fun logAndClearToggledGroups() {
+ LegacySafetyNetLogger.logPermissionsToggled(toggledGroups)
+ toggledGroups.clear()
+ }
+
+ fun getAutoRevokeChipParam(state: HibernationSettingState?): AutoRevokeChipParam? =
+ state?.let {
+ AutoRevokeChipParam(
+ labelRes = if (isHibernationEnabled()) {
+ R.string.unused_apps_label_v2
+ } else {
+ R.string.auto_revoke_label
+ },
+ visible = it.revocableGroupNames.isNotEmpty(),
+ checked = it.isEligibleForHibernation(),
+ onCheckedChanged = { checked ->
+ run {
+ viewModel.setAutoRevoke(checked)
+ Log.w(TAG, "setAutoRevoke $checked")
+ }
+ }
+ )
+ }
+
+ companion object {
+ const val DEBUG = false
+ const val TAG = WearAppPermissionGroupsFragment.LOG_TAG
+ }
+}
+
+data class PermissionGroupChipParam(
+ val group: AppPermissionGroup,
+ val perm: PermissionInfo? = null,
+ val label: String,
+ val summary: Int? = null,
+ val enabled: Boolean = true,
+ val checked: Boolean? = null,
+ val onClick: () -> Unit = {},
+ val onCheckedChanged: (Boolean) -> Unit = {}
+)
+
+data class AutoRevokeChipParam(
+ val labelRes: Int,
+ val visible: Boolean,
+ val checked: Boolean = false,
+ val onCheckedChanged: (Boolean) -> Unit
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
new file mode 100644
index 000000000..2d06ef950
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.res.stringResource
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.wear.elements.AlertDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs
+
+@Composable
+fun WearAppPermissionGroupsScreen(
+ helper: WearAppPermissionGroupsHelper
+) {
+ val packagePermGroups = helper.viewModel.packagePermGroupsLiveData.observeAsState(emptyMap())
+ val autoRevoke = helper.viewModel.autoRevokeLiveData.observeAsState(null)
+ val showRevokeDialog = helper.revokeDialogViewModel.showDialogLiveData.observeAsState(false)
+ var isLoading by remember { mutableStateOf(true) }
+
+ Box {
+ WearAppPermissionGroupsContent(
+ isLoading,
+ helper.getPermissionGroupChipParams(),
+ helper.getAutoRevokeChipParam(autoRevoke.value)
+ )
+ RevokeDialog(
+ showDialog = showRevokeDialog.value,
+ args = helper.revokeDialogViewModel.revokeDialogArgs
+ )
+ }
+
+ if (isLoading && packagePermGroups.value.isNotEmpty()) {
+ isLoading = false
+ }
+}
+
+@Composable
+internal fun WearAppPermissionGroupsContent(
+ isLoading: Boolean,
+ permissionGroupChipParams: List<PermissionGroupChipParam>,
+ autoRevokeChipParam: AutoRevokeChipParam?
+) {
+ ScrollableScreen(
+ title = stringResource(R.string.app_permissions),
+ isLoading = isLoading
+ ) {
+ if (permissionGroupChipParams.isEmpty()) {
+ item {
+ Chip(
+ label = stringResource(R.string.no_permissions),
+ onClick = {}
+ )
+ }
+ } else {
+ for (info in permissionGroupChipParams) {
+ item {
+ if (info.checked != null) {
+ ToggleChip(
+ checked = info.checked,
+ label = info.label,
+ enabled = info.enabled,
+ toggleControl = ToggleChipToggleControl.Switch,
+ onCheckedChanged = info.onCheckedChanged
+ )
+ } else {
+ Chip(
+ label = info.label,
+ secondaryLabel = info.summary?.let {
+ stringResource(info.summary)
+ },
+ enabled = info.enabled,
+ onClick = info.onClick
+ )
+ }
+ }
+ }
+ autoRevokeChipParam?.let {
+ if (it.visible) {
+ item {
+ ToggleChip(
+ checked = it.checked,
+ label = stringResource(it.labelRes),
+ labelMaxLine = 3,
+ toggleControl = ToggleChipToggleControl.Switch,
+ onCheckedChanged = it.onCheckedChanged
+ )
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+internal fun RevokeDialog(
+ showDialog: Boolean,
+ args: RevokeDialogArgs?
+) {
+ args?.let {
+ AlertDialog(
+ showDialog = showDialog,
+ message = stringResource(it.messageId),
+ onOKButtonClick = it.onOkButtonClick,
+ onCancelButtonClick = it.onCancelButtonClick,
+ scalingLazyListState = rememberScalingLazyListState()
+ )
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
new file mode 100644
index 000000000..fb9c2acdd
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.res.stringResource
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonState
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
+import com.android.permissioncontroller.permission.ui.wear.elements.AlertDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.ConfirmDialogArgs
+import com.android.settingslib.RestrictedLockUtils
+
+@Composable
+fun WearAppPermissionScreen(
+ title: String,
+ viewModel: AppPermissionViewModel,
+ confirmDialogViewModel: AppPermissionConfirmDialogViewModel,
+ onLocationSwitchChanged: (Boolean) -> Unit,
+ onGrantedStateChanged: (ButtonType, Boolean) -> Unit,
+ onFooterClicked: (RestrictedLockUtils.EnforcedAdmin) -> Unit,
+ onConfirmDialogOkButtonClick: (ConfirmDialogArgs) -> Unit,
+ onConfirmDialogCancelButtonClick: () -> Unit,
+ onAdvancedConfirmDialogOkButtonClick: (AdvancedConfirmDialogArgs) -> Unit,
+ onAdvancedConfirmDialogCancelButtonClick: () -> Unit
+) {
+ val buttonState = viewModel.buttonStateLiveData.observeAsState(emptyMap())
+ val detailResIds = viewModel.detailResIdLiveData.observeAsState(null)
+ val admin = viewModel.showAdminSupportLiveData.observeAsState(null)
+ var isLoading by remember { mutableStateOf(true) }
+ val showConfirmDialog = confirmDialogViewModel.showConfirmDialogLiveData.observeAsState(false)
+ val showAdvancedConfirmDialog =
+ confirmDialogViewModel.showAdvancedConfirmDialogLiveData.observeAsState(false)
+
+ Box {
+ WearAppPermissionContent(
+ title,
+ buttonState.value,
+ detailResIds.value,
+ admin.value,
+ isLoading,
+ onLocationSwitchChanged,
+ onGrantedStateChanged,
+ onFooterClicked,
+ )
+ ConfirmDialog(
+ showDialog = showConfirmDialog.value,
+ args = confirmDialogViewModel.confirmDialogArgs,
+ onOkButtonClick = onConfirmDialogOkButtonClick,
+ onCancelButtonClick = onConfirmDialogCancelButtonClick
+ )
+ AdvancedConfirmDialog(
+ showDialog = showAdvancedConfirmDialog.value,
+ args = confirmDialogViewModel.advancedConfirmDialogArgs,
+ onOkButtonClick = onAdvancedConfirmDialogOkButtonClick,
+ onCancelButtonClick = onAdvancedConfirmDialogCancelButtonClick
+ )
+ }
+ if (isLoading && buttonState.value.isNotEmpty()) {
+ isLoading = false
+ }
+}
+
+@Composable
+internal fun WearAppPermissionContent(
+ title: String,
+ buttonState: Map<ButtonType, ButtonState>,
+ detailResIds: Pair<Int, Int?>?,
+ admin: RestrictedLockUtils.EnforcedAdmin?,
+ isLoading: Boolean,
+ onLocationSwitchChanged: (Boolean) -> Unit,
+ onGrantedStateChanged: (ButtonType, Boolean) -> Unit,
+ onFooterClicked: (RestrictedLockUtils.EnforcedAdmin) -> Unit
+) {
+ ScrollableScreen(
+ title = title,
+ isLoading = isLoading
+ ) {
+ buttonState[ButtonType.LOCATION_ACCURACY]?.let {
+ if (it.isShown) {
+ item {
+ ToggleChip(
+ checked = it.isChecked,
+ enabled = it.isEnabled,
+ label = stringResource(R.string.app_permission_location_accuracy),
+ toggleControl = ToggleChipToggleControl.Switch,
+ onCheckedChanged = onLocationSwitchChanged,
+ labelMaxLine = Integer.MAX_VALUE
+ )
+ }
+ }
+ }
+ for (buttonType in buttonTypeOrder) {
+ buttonState[buttonType]?.let {
+ if (it.isShown) {
+ item {
+ ToggleChip(
+ checked = it.isChecked,
+ enabled = it.isEnabled,
+ label = labelsByButton(buttonType),
+ toggleControl = ToggleChipToggleControl.Radio,
+ onCheckedChanged = { checked ->
+ onGrantedStateChanged(buttonType, checked)
+ },
+ labelMaxLine = Integer.MAX_VALUE
+ )
+ }
+ }
+ }
+ }
+ detailResIds?.let {
+ item {
+ ListFooter(
+ description = stringResource(detailResIds.first),
+ iconRes = R.drawable.ic_info,
+ onClick = if (admin != null) {
+ { onFooterClicked(admin) }
+ } else {
+ null
+ }
+ )
+ }
+ }
+ }
+}
+
+internal val buttonTypeOrder = listOf(
+ ButtonType.ALLOW,
+ ButtonType.ALLOW_ALWAYS,
+ ButtonType.ALLOW_FOREGROUND,
+ ButtonType.ASK_ONCE,
+ ButtonType.ASK,
+ ButtonType.DENY,
+ ButtonType.DENY_FOREGROUND
+)
+
+@Composable
+internal fun labelsByButton(buttonType: ButtonType) = when (buttonType) {
+ ButtonType.ALLOW -> stringResource(R.string.app_permission_button_allow)
+ ButtonType.ALLOW_ALWAYS -> stringResource(R.string.app_permission_button_allow_always)
+ ButtonType.ALLOW_FOREGROUND -> stringResource(R.string.app_permission_button_allow_foreground)
+ ButtonType.ASK_ONCE -> stringResource(R.string.app_permission_button_ask)
+ ButtonType.ASK -> stringResource(R.string.app_permission_button_ask)
+ ButtonType.DENY -> stringResource(R.string.app_permission_button_deny)
+ ButtonType.DENY_FOREGROUND -> stringResource(R.string.app_permission_button_deny)
+ else -> ""
+}
+
+@Composable
+internal fun ConfirmDialog(
+ showDialog: Boolean,
+ args: ConfirmDialogArgs?,
+ onOkButtonClick: (ConfirmDialogArgs) -> Unit,
+ onCancelButtonClick: () -> Unit
+) {
+ args?.let {
+ AlertDialog(
+ showDialog = showDialog,
+ message = stringResource(it.messageId),
+ onOKButtonClick = {
+ onOkButtonClick(it)
+ },
+ onCancelButtonClick = onCancelButtonClick,
+ scalingLazyListState = rememberScalingLazyListState()
+ )
+ }
+}
+
+@Composable
+internal fun AdvancedConfirmDialog(
+ showDialog: Boolean,
+ args: AdvancedConfirmDialogArgs?,
+ onOkButtonClick: (AdvancedConfirmDialogArgs) -> Unit,
+ onCancelButtonClick: () -> Unit
+) {
+ args?.let {
+ AlertDialog(
+ showDialog = showDialog,
+ title = if (it.titleId != 0) {
+ stringResource(it.titleId)
+ } else {
+ ""
+ },
+ iconRes = it.iconId,
+ message = stringResource(it.messageId),
+ okButtonContentDescription = stringResource(it.positiveButtonTextId),
+ cancelButtonContentDescription = stringResource(it.negativeButtonTextId),
+ onOKButtonClick = {
+ onOkButtonClick(it)
+ },
+ onCancelButtonClick = onCancelButtonClick,
+ scalingLazyListState = rememberScalingLazyListState()
+ )
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt
new file mode 100644
index 000000000..3c59fb5ee
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.res.stringResource
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ALWAYS_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_FOREGROUND_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ONE_TIME_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DENY_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_BOTH_LOCATIONS
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.DIALOG_WITH_FINE_LOCATION_ONLY
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.LOCATION_ACCURACY_LAYOUT
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON
+import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_BUTTON
+import com.android.permissioncontroller.permission.ui.wear.GrantPermissionsWearViewHandler.BUTTON_RES_ID_TO_NUM
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.model.WearGrantPermissionsViewModel
+
+@Composable
+fun WearGrantPermissionsScreen(
+ viewModel: WearGrantPermissionsViewModel,
+ onButtonClicked: (Int) -> Unit,
+ onLocationSwitchChanged: (Boolean) -> Unit
+) {
+ val groupMessage = viewModel.groupMessageLiveData.observeAsState("")
+ val icon = viewModel.iconLiveData.observeAsState(null)
+ val detailMessage = viewModel.detailMessageLiveData.observeAsState(null)
+ val locationVisibilities = viewModel.locationVisibilitiesLiveData.observeAsState(emptyList())
+ val preciseLocationChecked = viewModel.preciseLocationCheckedLiveData.observeAsState(false)
+ val buttonVisibilities = viewModel.buttonVisibilitiesLiveData.observeAsState(emptyList())
+
+ ScrollableScreen(
+ showTimeText = false,
+ image = icon.value,
+ title = groupMessage.value,
+ subtitle = detailMessage.value
+ ) {
+ if (
+ locationVisibilities.value.getOrElse(LOCATION_ACCURACY_LAYOUT) { false } &&
+ locationVisibilities.value.getOrElse(DIALOG_WITH_BOTH_LOCATIONS) { false }
+ ) {
+ item {
+ ToggleChip(
+ checked = preciseLocationChecked.value,
+ onCheckedChanged = { onLocationSwitchChanged(it) },
+ label = stringResource(R.string.app_permission_location_accuracy),
+ toggleControl = ToggleChipToggleControl.Switch,
+ modifier = Modifier.fillMaxWidth(),
+ labelMaxLine = Integer.MAX_VALUE
+ )
+ }
+ }
+ for (i in 0 until BUTTON_RES_ID_TO_NUM.size()) {
+ val pos: Int = BUTTON_RES_ID_TO_NUM.valueAt(i)
+ if (buttonVisibilities.value.size <= pos) {
+ // initial value of buttonVisibilities is empty
+ break
+ }
+ if (buttonVisibilities.value[pos]) {
+ item {
+ Chip(
+ label =
+ getPrimaryText(
+ pos,
+ locationVisibilities.value,
+ labelsByButton(BUTTON_RES_ID_TO_NUM.valueAt(i))
+ ),
+ onClick = { onButtonClicked(BUTTON_RES_ID_TO_NUM.keyAt(i)) },
+ modifier = Modifier.fillMaxWidth(),
+ labelMaxLines = Integer.MAX_VALUE
+ )
+ }
+ }
+ }
+ }
+}
+
+fun setContent(
+ composeView: ComposeView,
+ viewModel: WearGrantPermissionsViewModel,
+ onButtonClicked: (Int) -> Unit,
+ onLocationSwitchChanged: (Boolean) -> Unit
+) {
+ composeView.setContent {
+ WearGrantPermissionsScreen(viewModel, onButtonClicked, onLocationSwitchChanged)
+ }
+}
+
+@Composable
+internal fun labelsByButton(grantPermissionsButtonType: Int) =
+ when (grantPermissionsButtonType) {
+ ALLOW_BUTTON -> stringResource(R.string.grant_dialog_button_allow)
+ ALLOW_ALWAYS_BUTTON -> stringResource(R.string.grant_dialog_button_allow_always)
+ ALLOW_FOREGROUND_BUTTON -> stringResource(R.string.grant_dialog_button_allow_foreground)
+ DENY_BUTTON -> stringResource(R.string.grant_dialog_button_deny)
+ DENY_AND_DONT_ASK_AGAIN_BUTTON -> stringResource(R.string.grant_dialog_button_deny)
+ ALLOW_ONE_TIME_BUTTON -> stringResource(R.string.grant_dialog_button_allow_one_time)
+ NO_UPGRADE_BUTTON -> stringResource(R.string.grant_dialog_button_no_upgrade)
+ NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON ->
+ stringResource(R.string.grant_dialog_button_no_upgrade)
+ NO_UPGRADE_OT_BUTTON -> stringResource(R.string.grant_dialog_button_no_upgrade_one_time)
+ NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON ->
+ stringResource(R.string.grant_dialog_button_no_upgrade_one_time)
+ else -> ""
+ }
+
+@Composable
+private fun getPrimaryText(pos: Int, locationVisibilities: List<Boolean>, default: String): String {
+ val isPreciseLocation: Boolean =
+ locationVisibilities.getOrElse(LOCATION_ACCURACY_LAYOUT) { false } &&
+ locationVisibilities.getOrElse(DIALOG_WITH_FINE_LOCATION_ONLY) { false }
+ var res: String = default
+ if (pos == ALLOW_FOREGROUND_BUTTON && isPreciseLocation) {
+ res = stringResource(R.string.grant_dialog_button_change_to_precise_location)
+ }
+ if ((pos == DENY_BUTTON || pos == DENY_AND_DONT_ASK_AGAIN_BUTTON) && isPreciseLocation) {
+ res = stringResource(R.string.grant_dialog_button_keey_approximate_location)
+ }
+ return res
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt
new file mode 100644
index 000000000..d24cb89a2
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.res.stringResource
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+
+@Composable
+fun WearManageCustomPermissionScreen(
+ viewModel: ManageCustomPermissionsViewModel,
+ onPermGroupClick: (String) -> Unit
+) {
+ val permissionGroups = viewModel.uiDataLiveData.observeAsState(emptyMap())
+ var isLoading by remember { mutableStateOf(true) }
+
+ WearManageCustomPermissionContent(
+ isLoading,
+ getPermGroupChipParams(permissionGroups.value),
+ onPermGroupClick
+ )
+
+ if (isLoading && permissionGroups.value.isNotEmpty()) {
+ isLoading = false
+ }
+}
+
+@Composable
+internal fun WearManageCustomPermissionContent(
+ isLoading: Boolean,
+ permGroupChipParams: List<PermGroupChipParam>,
+ onPermGroupClick: (String) -> Unit
+) {
+ ScrollableScreen(
+ title = stringResource(R.string.additional_permissions),
+ isLoading = isLoading
+ ) {
+ for (params in permGroupChipParams) {
+ item {
+ Chip(
+ label = params.label,
+ labelMaxLines = 3,
+ icon = params.icon,
+ secondaryLabel = params.secondaryLabel,
+ secondaryLabelMaxLines = 3,
+ onClick = {
+ onPermGroupClick(params.permGroupName)
+ }
+ )
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt
new file mode 100644
index 000000000..808a2169c
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment
+import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel
+
+class WearManageCustomPermissionsFragment : Fragment() {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val activity = requireActivity()
+ val application = activity.getApplication()
+ val sessionId: Long =
+ arguments?.getLong(Constants.EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
+ val viewModel = ViewModelProvider(
+ this,
+ ViewModelProvider.AndroidViewModelFactory.getInstance(application)
+ ).get(ManageCustomPermissionsViewModel::class.java)
+
+ val onPermGroupClick: (String) -> Unit = { permGroupName ->
+ viewModel.showPermissionApps(
+ this,
+ PermissionAppsFragment.createArgs(permGroupName, sessionId)
+ )
+ }
+
+ return ComposeView(activity).apply {
+ setContent {
+ WearManageCustomPermissionScreen(
+ viewModel,
+ onPermGroupClick
+ )
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt
new file mode 100644
index 000000000..94d994421
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.graphics.drawable.Drawable
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.model.livedatatypes.PermGroupPackagesUiInfo
+import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupIcon
+import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
+import com.android.permissioncontroller.permission.utils.StringUtils
+import java.text.Collator
+
+@Composable
+fun WearManageStandardPermissionScreen(
+ viewModel: ManageStandardPermissionsViewModel,
+ onPermGroupClick: (String) -> Unit,
+ onCustomPermissionsClick: () -> Unit,
+ onAutoRevokedClick: () -> Unit
+) {
+ val permissionGroups = viewModel.uiDataLiveData.observeAsState(emptyMap())
+ val numCustomPermGroups = viewModel.numCustomPermGroups.observeAsState(0)
+ val numAutoRevoked = viewModel.numAutoRevoked.observeAsState(0)
+ var isLoading by remember { mutableStateOf(true) }
+
+ WearManageStandardPermissionContent(
+ isLoading,
+ getPermGroupChipParams(permissionGroups.value),
+ numCustomPermGroups.value,
+ numAutoRevoked.value,
+ onPermGroupClick,
+ onCustomPermissionsClick,
+ onAutoRevokedClick
+ )
+
+ if (isLoading && permissionGroups.value.isNotEmpty()) {
+ isLoading = false
+ }
+}
+
+@Composable
+internal fun getPermGroupChipParams(
+ permissionGroups: Map<String, PermGroupPackagesUiInfo?>
+): List<PermGroupChipParam> {
+ val context = LocalContext.current
+ val collator = Collator.getInstance(context.resources.getConfiguration().getLocales().get(0))
+ val summary = if (context.resources.getBoolean(R.bool.config_useAlternativePermGroupSummary)) {
+ R.string.app_permissions_group_summary2
+ } else {
+ R.string.app_permissions_group_summary
+ }
+ return permissionGroups.mapNotNull {
+ val uiInfo = it.value ?: return@mapNotNull null
+ PermGroupChipParam(
+ permGroupName = it.key,
+ label = getPermGroupLabel(context, it.key).toString(),
+ icon = getPermGroupIcon(context, it.key),
+ secondaryLabel = stringResource(
+ summary,
+ uiInfo.nonSystemGranted,
+ uiInfo.nonSystemTotal
+ )
+ )
+ }.sortedWith { lhs, rhs ->
+ collator.compare(lhs.label, rhs.label)
+ }.toList()
+}
+
+@Composable
+internal fun WearManageStandardPermissionContent(
+ isLoading: Boolean,
+ permGroupChipParams: List<PermGroupChipParam>,
+ numCustomPermGroups: Int,
+ numAutoRevoked: Int,
+ onPermGroupClick: (String) -> Unit,
+ onCustomPermissionsClick: () -> Unit,
+ onAutoRevokedClick: () -> Unit
+) {
+ ScrollableScreen(
+ title = stringResource(R.string.app_permission_manager),
+ isLoading = isLoading
+ ) {
+ for (params in permGroupChipParams) {
+ item {
+ Chip(
+ label = params.label,
+ labelMaxLines = 3,
+ icon = params.icon,
+ secondaryLabel = params.secondaryLabel,
+ secondaryLabelMaxLines = 3,
+ onClick = {
+ onPermGroupClick(params.permGroupName)
+ }
+ )
+ }
+ }
+
+ if (numCustomPermGroups > 0) {
+ item {
+ Chip(
+ label = stringResource(R.string.additional_permissions),
+ labelMaxLines = 3,
+ icon = R.drawable.ic_more_horizontal,
+ secondaryLabel = StringUtils.getIcuPluralsString(
+ LocalContext.current,
+ R.string.additional_permissions_more,
+ numCustomPermGroups
+ ),
+ secondaryLabelMaxLines = 3,
+ onClick = onCustomPermissionsClick
+ )
+ }
+ }
+
+ if (numAutoRevoked > 0) {
+ item {
+ Chip(
+ label = stringResource(R.string.auto_revoke_permission_notification_title),
+ labelMaxLines = 3,
+ icon = R.drawable.ic_info,
+ secondaryLabel = stringResource(R.string.auto_revoke_setting_subtitle),
+ secondaryLabelMaxLines = 3,
+ onClick = onAutoRevokedClick
+ )
+ }
+ }
+ }
+}
+
+internal data class PermGroupChipParam(
+ val permGroupName: String,
+ val label: String,
+ val icon: Drawable?,
+ val secondaryLabel: String,
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt
new file mode 100644
index 000000000..349b18340
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.permission.ui.handheld.ManageCustomPermissionsFragment
+import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment
+import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel
+
+class WearManageStandardPermissionsFragment : Fragment() {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val activity = requireActivity()
+ val application = activity.getApplication()
+ val sessionId: Long =
+ arguments?.getLong(Constants.EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
+ val viewModel: ManageStandardPermissionsViewModel = ViewModelProvider(
+ this,
+ ViewModelProvider.AndroidViewModelFactory.getInstance(application)
+ ).get(ManageStandardPermissionsViewModel::class.java)
+
+ val onPermGroupClick: (String) -> Unit = { permGroupName ->
+ viewModel.showPermissionApps(
+ this,
+ PermissionAppsFragment.createArgs(permGroupName, sessionId)
+ )
+ }
+ val onCustomPermGroupClick = {
+ viewModel.showCustomPermissions(
+ this,
+ ManageCustomPermissionsFragment.createArgs(sessionId)
+ )
+ }
+ val onAutoRevokeClick = {
+ viewModel.showAutoRevoke(this, WearUnusedAppsFragment.createArgs(sessionId))
+ }
+
+ return ComposeView(activity).apply {
+ setContent {
+ WearManageStandardPermissionScreen(
+ viewModel,
+ onPermGroupClick,
+ onCustomPermGroupClick,
+ onAutoRevokeClick
+ )
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt
new file mode 100644
index 000000000..16ba9c148
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsFragment.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.Manifest
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.modules.utils.build.SdkLevel
+import com.android.permissioncontroller.Constants
+import com.android.permissioncontroller.permission.ui.handheld.AppPermissionFragment
+import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel
+import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModelFactory
+
+/**
+ * This is a condensed version of
+ * [com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment],
+ * tailored for Wear.
+ *
+ * Show and manage apps which request a single permission group.
+ *
+ * <p>Shows a list of apps which request at least on permission of this group.
+ */
+class WearPermissionAppsFragment : Fragment() {
+ private val LOG_TAG = "PermissionAppsFragment"
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val permGroupName = arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME)
+ ?: arguments?.getString(Intent.EXTRA_PERMISSION_NAME)
+ ?: throw RuntimeException("Permission group name must not be null.")
+ val sessionId: Long =
+ arguments?.getLong(Constants.EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
+ val isStorageAndLessThanT = !SdkLevel.isAtLeastT() &&
+ permGroupName == Manifest.permission_group.STORAGE
+
+ val activity = requireActivity()
+ val factory = PermissionAppsViewModelFactory(
+ activity.getApplication(),
+ permGroupName,
+ this,
+ Bundle()
+ )
+ val viewModel =
+ ViewModelProvider(this, factory).get(PermissionAppsViewModel::class.java)
+
+ val onAppClick: (String, UserHandle, String) -> Unit = {
+ packageName, user, category ->
+ run {
+ viewModel.navigateToAppPermission(
+ this,
+ packageName,
+ user,
+ AppPermissionFragment.createArgs(
+ packageName,
+ null,
+ permGroupName,
+ user,
+ this::class.java.name,
+ sessionId,
+ category
+ )
+ )
+ }
+ }
+
+ val onShowSystemClick: (Boolean) -> Unit = { showSystem ->
+ run {
+ viewModel.updateShowSystem(showSystem)
+ }
+ }
+
+ val logPermissionAppsFragmentCreated:
+ (String, UserHandle, Long, Boolean, Boolean, Boolean) -> Unit =
+ { packageName, user, viewId, isAllowed, isAllowedForeground, isDenied ->
+ run {
+ viewModel.logPermissionAppsFragmentCreated(
+ packageName, user, viewId, isAllowed,
+ isAllowedForeground, isDenied, sessionId, activity.getApplication(),
+ permGroupName, LOG_TAG
+ )
+ }
+ }
+
+ return ComposeView(requireContext()).apply {
+ setContent {
+ WearPermissionAppsScreen(
+ WearPermissionAppsHelper(
+ activity.getApplication(),
+ permGroupName,
+ viewModel,
+ isStorageAndLessThanT,
+ onAppClick,
+ onShowSystemClick,
+ logPermissionAppsFragmentCreated
+ )
+ )
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt
new file mode 100644
index 000000000..3a21e3034
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsHelper.kt
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.app.Application
+import android.graphics.drawable.Drawable
+import android.os.UserHandle
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.Category
+import com.android.permissioncontroller.permission.ui.model.PermissionAppsViewModel
+import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupDescription
+import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel
+import com.android.settingslib.utils.applications.AppUtils
+import java.text.Collator
+import java.util.Random
+
+/**
+ * Helper class for WearPermissionsAppScreen.
+ */
+class WearPermissionAppsHelper(
+ val application: Application,
+ val permGroupName: String,
+ val viewModel: PermissionAppsViewModel,
+ private val isStorageAndLessThanT: Boolean,
+ private val onAppClick: (String, UserHandle, String) -> Unit,
+ val onShowSystemClick: (Boolean) -> Unit,
+ val logFragmentCreated: (String, UserHandle, Long, Boolean, Boolean, Boolean) -> Unit
+) {
+ fun categorizedAppsLiveData() = viewModel.categorizedAppsLiveData
+ fun hasSystemAppsLiveData() = viewModel.hasSystemAppsLiveData
+ fun shouldShowSystemLiveData() = viewModel.shouldShowSystemLiveData
+ fun showAlways() = viewModel.showAllowAlwaysStringLiveData.value ?: false
+ fun getTitle() = getPermGroupLabel(application, permGroupName).toString()
+ fun getSubTitle() = getPermGroupDescription(application, permGroupName).toString()
+ fun getChipsByCategory(
+ categorizedApps: Map<Category, List<Pair<String, UserHandle>>>
+ ): Map<String, List<ChipInfo>> {
+ val chipsByCategory: MutableMap<String, MutableList<ChipInfo>> = HashMap()
+
+ val context = application
+ val collator = Collator.getInstance(context.resources.configuration.locales.get(0))
+ val comparator = ChipComparator(collator)
+
+ val viewIdForLogging = Random().nextLong()
+ for (category in Category.values()) {
+ if (category == Category.ALLOWED && isStorageAndLessThanT) {
+ val allowedList = categorizedApps[Category.ALLOWED]
+ if (!allowedList.isNullOrEmpty()) {
+ allowedList.partition { p ->
+ viewModel.packageHasFullStorage(
+ p.first,
+ p.second
+ )
+ }.let {
+ if (it.first.isNotEmpty()) {
+ chipsByCategory[STORAGE_ALLOWED_FULL] =
+ convertToChips(category, it.first, viewIdForLogging, comparator)
+ }
+ if (it.second.isNotEmpty()) {
+ chipsByCategory[STORAGE_ALLOWED_SCOPED] =
+ convertToChips(category, it.second, viewIdForLogging, comparator)
+ }
+ }
+ }
+ continue
+ }
+ val list = categorizedApps[category]
+ if (!list.isNullOrEmpty()) {
+ chipsByCategory[category.categoryName] =
+ convertToChips(category, list, viewIdForLogging, comparator)
+ }
+ }
+
+ // Add no_apps chips to allowed and denied if it doesn't have an app.
+ addNoAppsIfNeeded(chipsByCategory)
+ return chipsByCategory
+ }
+
+ private fun convertToChips(
+ category: Category,
+ list: List<Pair<String, UserHandle>>,
+ viewIdForLogging: Long,
+ comparator: Comparator<ChipInfo>
+ ) =
+ list.map { p ->
+ createAppChipInfo(
+ application,
+ p.first,
+ p.second,
+ category,
+ onAppClick,
+ viewIdForLogging
+ )
+ }.sortedWith(comparator).toMutableList()
+
+ fun setCreationLogged(isLogged: Boolean) {
+ viewModel.creationLogged = isLogged
+ }
+
+ private fun createAppChipInfo(
+ application: Application,
+ packageName: String,
+ user: UserHandle,
+ category: Category,
+ onClick: (packageName: String, user: UserHandle, category: String) -> Unit,
+ viewIdForLogging: Long
+ ): ChipInfo {
+ if (!viewModel.creationLogged) {
+ logFragmentCreated(
+ packageName,
+ user,
+ viewIdForLogging,
+ category == Category.ALLOWED,
+ category == Category.ALLOWED_FOREGROUND,
+ category == Category.DENIED
+ )
+ }
+ return ChipInfo(
+ title = KotlinUtils.getPackageLabel(application, packageName, user),
+ contentDescription = AppUtils.getAppContentDescription(
+ application,
+ packageName,
+ user.getIdentifier()
+ ),
+ icon = KotlinUtils.getBadgedPackageIcon(application, packageName, user),
+ onClick = { onClick(packageName, user, category.categoryName) }
+ )
+ }
+
+ private fun addNoAppsIfNeeded(chipsByCategory: MutableMap<String, MutableList<ChipInfo>>) {
+ addNoAppsToAllowed(chipsByCategory)
+ addNoAppsToDenied(chipsByCategory)
+ }
+
+ private fun addNoAppsToAllowed(chipsByCategory: MutableMap<String, MutableList<ChipInfo>>) {
+ if (isStorageAndLessThanT) {
+ // For the storage permission,
+ // allowed category is split into allowed_full and allowed_scoped categories,
+ // add no_apps chip to the categories.
+ addNoAppsTo(chipsByCategory, STORAGE_ALLOWED_FULL, R.string.no_apps_allowed_full)
+ addNoAppsTo(chipsByCategory, STORAGE_ALLOWED_SCOPED, R.string.no_apps_allowed_scoped)
+ return
+ }
+ addNoAppsTo(chipsByCategory, Category.ALLOWED.categoryName, R.string.no_apps_allowed)
+ }
+
+ private fun addNoAppsToDenied(chipsByCategory: MutableMap<String, MutableList<ChipInfo>>) {
+ addNoAppsTo(chipsByCategory, Category.DENIED.categoryName, R.string.no_apps_denied)
+ }
+
+ private fun addNoAppsTo(
+ chipsByCategory: MutableMap<String, MutableList<ChipInfo>>,
+ categoryName: String,
+ titleResId: Int
+ ) {
+ if (chipsByCategory[categoryName].isNullOrEmpty()) {
+ chipsByCategory[categoryName] = mutableListOf(
+ ChipInfo(
+ title = application.resources.getString(titleResId),
+ enabled = false
+ )
+ )
+ }
+ }
+
+ companion object {
+ private const val STORAGE_ALLOWED_FULL = "allowed_storage_full"
+ private const val STORAGE_ALLOWED_SCOPED = "allowed_storage_scoped"
+ }
+}
+
+class ChipInfo(
+ val title: String,
+ val contentDescription: String? = null,
+ val onClick: () -> Unit = {},
+ val icon: Drawable? = null,
+ val enabled: Boolean = true
+)
+
+internal class ChipComparator(
+ val collator: Collator
+) : Comparator<ChipInfo> {
+ override fun compare(lhs: ChipInfo, rhs: ChipInfo): Int {
+ var result = collator.compare(lhs.title, rhs.title)
+ if (result == 0) {
+ result = lhs.title.compareTo(rhs.title)
+ }
+ return result
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
new file mode 100644
index 000000000..77e64383a
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.wear.compose.material.Text
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.Category
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ListSubheader
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+
+/**
+ * Compose the screen associated to a [WearPermissionAppsFragment].
+ */
+@Composable
+fun WearPermissionAppsScreen(
+ helper: WearPermissionAppsHelper
+) {
+ val categorizedApps = helper.categorizedAppsLiveData().observeAsState(emptyMap())
+ val hasSystemApps = helper.hasSystemAppsLiveData().observeAsState(false)
+ val showSystem = helper.shouldShowSystemLiveData().observeAsState(false)
+ var isLoading by remember { mutableStateOf(true) }
+
+ val title = helper.getTitle()
+ val subTitle = helper.getSubTitle()
+ val showAlways = helper.showAlways()
+ val chipsByCategory = helper.getChipsByCategory(categorizedApps.value)
+
+ WearPermissionAppsContent(
+ chipsByCategory,
+ showSystem.value,
+ hasSystemApps.value,
+ title,
+ subTitle,
+ showAlways,
+ isLoading,
+ helper.onShowSystemClick
+ )
+
+ if (isLoading && categorizedApps.value.isNotEmpty()) {
+ isLoading = false
+ }
+ helper.setCreationLogged(true)
+}
+
+@Composable
+internal fun WearPermissionAppsContent(
+ chipsByCategory: Map<String, List<ChipInfo>>,
+ showSystem: Boolean,
+ hasSystemApps: Boolean,
+ title: String,
+ subtitle: String,
+ showAlways: Boolean,
+ isLoading: Boolean,
+ onShowSystemClick: (showSystem: Boolean) -> Unit
+) {
+ ScrollableScreen (
+ title = title,
+ subtitle = subtitle,
+ isLoading = isLoading
+ ) {
+ for (category in categoryOrder) {
+ val chips = chipsByCategory[category]
+ if (chips.isNullOrEmpty()) {
+ continue
+ }
+ item {
+ ListSubheader{
+ Text(text = stringResource(getCategoryString(category, showAlways)))
+ }
+ }
+ chips.forEach {
+ item {
+ Chip(
+ label = it.title,
+ labelMaxLines = Int.MAX_VALUE,
+ icon = it.icon,
+ enabled = it.enabled,
+ onClick = {
+ it.onClick()
+ },
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+ }
+ }
+
+ if (hasSystemApps) {
+ item {
+ Chip(
+ label = if (showSystem) {
+ stringResource(R.string.menu_hide_system)
+ } else {
+ stringResource(R.string.menu_show_system)
+ },
+ labelMaxLines = Int.MAX_VALUE,
+ onClick = {
+ onShowSystemClick(!showSystem)
+ },
+ modifier = Modifier.fillMaxWidth(),
+ )
+ }
+ }
+ }
+}
+
+internal fun getCategoryString(category: String, showAlways: Boolean) =
+ when (category) {
+ "allowed_storage_full" -> R.string.allowed_storage_full
+ "allowed_storage_scoped" -> R.string.allowed_storage_scoped
+ Category.ALLOWED.categoryName ->
+ if (showAlways) {
+ R.string.allowed_always_header
+ } else {
+ R.string.allowed_header
+ }
+ Category.ALLOWED_FOREGROUND.categoryName -> R.string.allowed_foreground_header
+ Category.ASK.categoryName -> R.string.ask_header
+ Category.DENIED.categoryName -> R.string.denied_header
+ else -> throw IllegalArgumentException("Wrong category: $category")
+ }
+
+internal val categoryOrder = listOf(
+ "allowed_storage_full",
+ "allowed_storage_scoped",
+ Category.ALLOWED.categoryName,
+ Category.ALLOWED_FOREGROUND.categoryName,
+ Category.ASK.categoryName,
+ Category.DENIED.categoryName
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt
new file mode 100644
index 000000000..fb89e02a1
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.Manifest
+import android.content.Context
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.UserHandle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
+import com.android.permissioncontroller.Constants.INVALID_SESSION_ID
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPackageInfo
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod.Companion.allPeriods
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModelFactory
+import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel.UnusedAppChip
+import com.android.permissioncontroller.permission.utils.KotlinUtils
+import com.android.settingslib.utils.applications.AppUtils
+import java.text.Collator
+
+/**
+ * This is a condensed version of
+ * [com.android.permissioncontroller.permission.ui.UnusedAppsFragment.kt], tailored for Wear.
+ *
+ * A fragment displaying all applications that are unused as well as the option to remove them and
+ * to open them.
+ */
+class WearUnusedAppsFragment : Fragment() {
+ private lateinit var activity: FragmentActivity
+ private lateinit var context: Context
+ private lateinit var viewModel: UnusedAppsViewModel
+ private lateinit var wearViewModel: WearUnusedAppsViewModel
+ private lateinit var collator: Collator
+ private var sessionId: Long = 0L
+ private var isFirstLoad = false
+ private var categoryVisibilities: MutableList<Boolean> =
+ MutableList(UnusedPeriod.values().size) { false }
+ private var unusedAppsMap: MutableMap<UnusedPeriod, MutableMap<String, UnusedAppChip>> =
+ initUnusedAppsMap()
+
+ companion object {
+ private const val SHOW_LOAD_DELAY_MS = 200L
+ private val LOG_TAG = WearUnusedAppsFragment::class.java.simpleName
+
+ /**
+ * Create the args needed for this fragment
+ *
+ * @param sessionId The current session Id
+ * @return A bundle containing the session Id
+ */
+ @JvmStatic
+ fun createArgs(sessionId: Long): Bundle {
+ val bundle = Bundle()
+ bundle.putLong(EXTRA_SESSION_ID, sessionId)
+ return bundle
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ isFirstLoad = true
+ context = requireContext()
+ collator =
+ Collator.getInstance(context.getResources().getConfiguration().getLocales().get(0))
+ activity = requireActivity()
+ val application = activity.getApplication()
+ sessionId = arguments!!.getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)
+ val factory = UnusedAppsViewModelFactory(activity.application, sessionId)
+ viewModel = ViewModelProvider(this, factory).get(UnusedAppsViewModel::class.java)
+ wearViewModel =
+ ViewModelProvider(
+ this,
+ ViewModelProvider.AndroidViewModelFactory.getInstance(application)
+ )
+ .get(WearUnusedAppsViewModel::class.java)
+ viewModel.unusedPackageCategoriesLiveData.observe(
+ this,
+ Observer {
+ it?.let { pkgs ->
+ updatePackages(pkgs)
+ updateWearViewModel(false)
+ }
+ }
+ )
+
+ if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) {
+ val handler = Handler(Looper.getMainLooper())
+ handler.postDelayed(
+ {
+ if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) {
+ wearViewModel.loadingLiveData.value = true
+ } else {
+ updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!)
+ updateWearViewModel(false)
+ }
+ },
+ SHOW_LOAD_DELAY_MS
+ )
+ } else {
+ updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!)
+ updateWearViewModel(false)
+ }
+
+ return ComposeView(activity).apply { setContent { WearUnusedAppsScreen(wearViewModel) } }
+ }
+
+ private fun initUnusedAppsMap(): MutableMap<UnusedPeriod, MutableMap<String, UnusedAppChip>> {
+ val res = mutableMapOf<UnusedPeriod, MutableMap<String, UnusedAppChip>>()
+ for (period in allPeriods) {
+ res.put(period, mutableMapOf())
+ }
+ return res
+ }
+
+ private fun updatePackages(categorizedPackages: Map<UnusedPeriod, List<UnusedPackageInfo>>) {
+ // Remove stale unused app chips
+ for (period in allPeriods) {
+ val it: MutableIterator<Map.Entry<String, UnusedAppChip>> =
+ unusedAppsMap[period]!!.entries.iterator()
+ while (it.hasNext()) {
+ val contains =
+ categorizedPackages[period]?.any { (pkgName, user, _) ->
+ val key = createKey(pkgName, user)
+ it.next().key == key
+ }
+ if (contains != true) {
+ it.remove()
+ }
+ }
+ }
+
+ var allCategoriesEmpty = true
+ for ((period, packages) in categorizedPackages) {
+ categoryVisibilities.set(periodToIndex(period), packages.isNotEmpty())
+ if (packages.isNotEmpty()) {
+ allCategoriesEmpty = false
+ }
+
+ for ((pkgName, user, _, permSet) in packages) {
+ val revokedPerms = permSet.toList()
+ val key = createKey(pkgName, user)
+
+ if (!unusedAppsMap[period]!!.containsKey(key)) {
+ val mostImportant = getMostImportantGroup(revokedPerms)
+ val importantLabel = KotlinUtils.getPermGroupLabel(context, mostImportant)
+ val summary =
+ when {
+ revokedPerms.isEmpty() -> null
+ revokedPerms.size == 1 ->
+ getString(R.string.auto_revoked_app_summary_one, importantLabel)
+ revokedPerms.size == 2 -> {
+ val otherLabel =
+ if (revokedPerms[0] == mostImportant) {
+ KotlinUtils.getPermGroupLabel(context, revokedPerms[1])
+ } else {
+ KotlinUtils.getPermGroupLabel(context, revokedPerms[0])
+ }
+ getString(
+ R.string.auto_revoked_app_summary_two,
+ importantLabel,
+ otherLabel
+ )
+ }
+ else ->
+ getString(
+ R.string.auto_revoked_app_summary_many,
+ importantLabel,
+ "${revokedPerms.size - 1}"
+ )
+ }
+
+ val onChipClicked: () -> Unit = {
+ run {
+ viewModel.navigateToAppInfo(pkgName, user, sessionId)
+ }
+ }
+
+ val chip =
+ UnusedAppChip(
+ KotlinUtils.getPackageLabel(activity.application, pkgName, user),
+ summary,
+ KotlinUtils.getBadgedPackageIcon(activity.application, pkgName, user),
+ AppUtils.getAppContentDescription(
+ context,
+ pkgName,
+ user.getIdentifier()
+ ),
+ onChipClicked
+ )
+ unusedAppsMap[period]!!.put(key, chip)
+ }
+ }
+
+ // Sort the chips
+ unusedAppsMap[period] =
+ unusedAppsMap[period]!!
+ .toList()
+ .sortedWith(Comparator { lhs, rhs -> compareUnusedApps(lhs, rhs) })
+ .toMap()
+ .toMutableMap()
+ }
+
+ wearViewModel.infoMsgCategoryVisibilityLiveData.value = !allCategoriesEmpty
+
+ if (isFirstLoad) {
+ if (categorizedPackages.any { (_, packages) -> packages.isNotEmpty() }) {
+ isFirstLoad = false
+ }
+ Log.i(LOG_TAG, "sessionId: $sessionId Showed Auto Revoke Page")
+ for (period in allPeriods) {
+ Log.i(
+ LOG_TAG,
+ "sessionId: $sessionId $period unused: " + "${categorizedPackages[period]}"
+ )
+ for (revokedPackageInfo in categorizedPackages[period]!!) {
+ for (groupName in revokedPackageInfo.revokedGroups) {
+ val isNewlyRevoked = period.isNewlyUnused()
+ viewModel.logAppView(
+ revokedPackageInfo.packageName,
+ revokedPackageInfo.user,
+ groupName,
+ isNewlyRevoked
+ )
+ }
+ }
+ }
+ }
+ }
+
+ private fun createKey(packageName: String, user: UserHandle): String {
+ return "$packageName:${user.identifier}"
+ }
+
+ private fun periodToIndex(period: UnusedPeriod): Int {
+ when (period) {
+ UnusedPeriod.ONE_MONTH -> return 0
+ UnusedPeriod.THREE_MONTHS -> return 1
+ UnusedPeriod.SIX_MONTHS -> return 2
+ }
+ }
+
+ private fun getMostImportantGroup(groupNames: List<String>): String {
+ return when {
+ groupNames.contains(Manifest.permission_group.LOCATION) ->
+ Manifest.permission_group.LOCATION
+ groupNames.contains(Manifest.permission_group.MICROPHONE) ->
+ Manifest.permission_group.MICROPHONE
+ groupNames.contains(Manifest.permission_group.CAMERA) ->
+ Manifest.permission_group.CAMERA
+ groupNames.contains(Manifest.permission_group.CONTACTS) ->
+ Manifest.permission_group.CONTACTS
+ groupNames.contains(Manifest.permission_group.STORAGE) ->
+ Manifest.permission_group.STORAGE
+ groupNames.contains(Manifest.permission_group.CALENDAR) ->
+ Manifest.permission_group.CALENDAR
+ groupNames.isNotEmpty() -> groupNames[0]
+ else -> ""
+ }
+ }
+
+ private fun compareUnusedApps(
+ lhs: Pair<String, UnusedAppChip>,
+ rhs: Pair<String, UnusedAppChip>
+ ): Int {
+ var result = collator.compare(lhs.second.label, rhs.second.label)
+ if (result == 0) {
+ result = collator.compare(lhs.first, rhs.first)
+ }
+ return result
+ }
+
+ private fun updateWearViewModel(isLoading: Boolean) {
+ wearViewModel.loadingLiveData.value = isLoading
+ wearViewModel.unusedPeriodCategoryVisibilitiesLiveData.setValue(categoryVisibilities)
+ wearViewModel.unusedAppChipsLiveData.setValue(unusedAppsMap)
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt
new file mode 100644
index 000000000..7c2487004
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.wear
+
+import android.icu.text.MessageFormat
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.res.stringResource
+import androidx.wear.compose.material.Text
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.hibernation.isHibernationEnabled
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod.Companion.allPeriods
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.Icon
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel
+
+@Composable
+fun WearUnusedAppsScreen(viewModel: WearUnusedAppsViewModel) {
+ val loading = viewModel.loadingLiveData.observeAsState(true)
+ val unusedPeriodCategoryVisibilities =
+ viewModel.unusedPeriodCategoryVisibilitiesLiveData.observeAsState(emptyList())
+ val infoMsgCategoryVisibility =
+ viewModel.infoMsgCategoryVisibilityLiveData.observeAsState(false)
+ val unusedAppChips = viewModel.unusedAppChipsLiveData.observeAsState(mutableMapOf())
+
+ ScrollableScreen(
+ showTimeText = true,
+ title = getScreenTitle(),
+ isLoading = loading.value,
+ subtitle = getSubTitle(!infoMsgCategoryVisibility.value)
+ ) {
+ for (period in allPeriods) {
+ if (!unusedAppChips.value.containsKey(period)) {
+ continue
+ }
+ item {
+ val pos = posByPeriod(period)
+ if (unusedPeriodCategoryVisibilities.value.getOrElse(pos) { false }) {
+ Text(text = categoryTitleByPeriod(period))
+ }
+ }
+ for (unusedAppChip in unusedAppChips.value[period]!!.values) {
+ item {
+ Chip(
+ label = unusedAppChip.label,
+ secondaryLabel = unusedAppChip.summary,
+ icon = unusedAppChip.icon,
+ iconContentDescription = unusedAppChip.contentDescription,
+ onClick = unusedAppChip.onClick
+ )
+ }
+ }
+ }
+ // For info_msg_category
+ if (infoMsgCategoryVisibility.value) {
+ item { Icon(icon = R.drawable.ic_info_outline, contentDescription = null) }
+ if (isHibernationEnabled()) {
+ item { Text(text = stringResource(R.string.unused_apps_page_summary)) }
+ } else {
+ item { Text(text = stringResource(R.string.auto_revoked_apps_page_summary)) }
+ item { Text(text = stringResource(R.string.auto_revoke_open_app_message)) }
+ }
+ }
+ }
+}
+
+@Composable
+private fun getScreenTitle() =
+ if (isHibernationEnabled()) {
+ stringResource(R.string.unused_apps_page_title)
+ } else {
+ stringResource(R.string.permission_removed_page_title)
+ }
+
+@Composable
+private fun getSubTitle(shouldShow: Boolean) =
+ if (shouldShow) {
+ stringResource(R.string.no_unused_apps)
+ } else {
+ null
+ }
+
+@Composable
+private fun posByPeriod(period: UnusedPeriod) =
+ when (period) {
+ UnusedPeriod.ONE_MONTH -> 0
+ UnusedPeriod.THREE_MONTHS -> 1
+ UnusedPeriod.SIX_MONTHS -> 2
+ }
+
+@Composable
+private fun categoryTitleByPeriod(period: UnusedPeriod) =
+ MessageFormat.format(
+ stringResource(R.string.last_opened_category_title),
+ mapOf("count" to period.months)
+ )
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt
new file mode 100644
index 000000000..c20959f7a
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.compose.foundation.layout.height
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+
+/** Adjusts height of the chip as per the font scale. */
+public fun Modifier.adjustChipHeightToFontScale(fontScale: Float, padding: Dp = 0.dp): Modifier =
+ if (fontScale > 1) {
+ this.then(Modifier.height(60.dp + padding))
+ } else {
+ this
+ } \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt
new file mode 100644
index 000000000..06d8acaba
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.material.ButtonDefaults
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import androidx.wear.compose.material.dialog.Alert
+import androidx.wear.compose.material.dialog.Dialog
+
+/**
+ * This component is an alternative to [Alert], providing the following:
+ * - a convenient way of passing a title and a message;
+ * - default positive and negative buttons;
+ * - wrapped in a [Dialog];
+ */
+@Composable
+public fun AlertDialog(
+ message: String,
+ iconRes: Int? = null,
+ onCancelButtonClick: () -> Unit,
+ onOKButtonClick: () -> Unit,
+ showDialog: Boolean,
+ scalingLazyListState: ScalingLazyListState,
+ modifier: Modifier = Modifier,
+ title: String = "",
+ okButtonContentDescription: String = stringResource(android.R.string.ok),
+ cancelButtonContentDescription: String = stringResource(android.R.string.cancel)
+) {
+ Dialog(
+ showDialog = showDialog,
+ onDismissRequest = onCancelButtonClick,
+ scrollState = scalingLazyListState,
+ modifier = modifier
+ ) {
+ Alert(
+ title = title,
+ iconRes = iconRes,
+ body = message,
+ scrollState = scalingLazyListState,
+ onCancelButtonClick = onCancelButtonClick,
+ onOKButtonClick = onOKButtonClick,
+ okButtonContentDescription = okButtonContentDescription,
+ cancelButtonContentDescription = cancelButtonContentDescription
+ )
+ }
+}
+
+/**
+ * This component is an alternative to [Alert], providing the following:
+ * - a convenient way of passing a title and a message;
+ * - default one button;
+ * - wrapped in a [Dialog];
+ */
+@Composable
+fun SingleButtonAlertDialog(
+ message: String,
+ iconRes: Int? = null,
+ onButtonClick: () -> Unit,
+ showDialog: Boolean,
+ scalingLazyListState: ScalingLazyListState,
+ modifier: Modifier = Modifier,
+ title: String = "",
+ buttonContentDescription: String = stringResource(android.R.string.ok)
+) {
+ Dialog(
+ showDialog = showDialog,
+ onDismissRequest = {},
+ scrollState = scalingLazyListState,
+ modifier = modifier
+ ) {
+ SingleButtonAlert(
+ title = title,
+ iconRes = iconRes,
+ body = message,
+ scrollState = scalingLazyListState,
+ onButtonClick = onButtonClick,
+ buttonContentDescription = buttonContentDescription
+ )
+ }
+}
+
+@Composable
+internal fun Alert(
+ title: String,
+ iconRes: Int? = null,
+ body: String,
+ scrollState: ScalingLazyListState,
+ onCancelButtonClick: () -> Unit,
+ onOKButtonClick: () -> Unit,
+ okButtonContentDescription: String,
+ cancelButtonContentDescription: String
+) {
+ Alert(
+ contentPadding = DefaultContentPadding(),
+ scrollState = scrollState,
+ title = { AlertTitleText(title) },
+ icon = { AlertIcon(iconRes) },
+ content = { AlertBodyText(body) },
+ negativeButton = { NegativeButton(onCancelButtonClick, cancelButtonContentDescription) },
+ positiveButton = { PositiveButton(onOKButtonClick, okButtonContentDescription) }
+ )
+}
+
+@Composable
+private fun SingleButtonAlert(
+ title: String,
+ iconRes: Int? = null,
+ body: String,
+ scrollState: ScalingLazyListState,
+ isOkButton: Boolean = true,
+ onButtonClick: () -> Unit,
+ buttonContentDescription: String,
+) {
+ Alert(
+ contentPadding = DefaultContentPadding(),
+ title = { AlertTitleText(title) },
+ scrollState = scrollState,
+ icon = { AlertIcon(iconRes) },
+ message = { AlertBodyText(body) }
+ ) {
+ item {
+ if (isOkButton) {
+ PositiveButton(onButtonClick, buttonContentDescription)
+ } else {
+ NegativeButton(onButtonClick, buttonContentDescription)
+ }
+ }
+ }
+}
+
+@Composable private fun DefaultContentPadding() = PaddingValues(top = 24.dp, bottom = 24.dp)
+
+@Composable
+private fun AlertTitleText(title: String) =
+ Text(
+ text = title,
+ color = MaterialTheme.colors.onBackground,
+ textAlign = TextAlign.Center,
+ maxLines = 3,
+ style = MaterialTheme.typography.title3
+ )
+
+@Composable
+private fun AlertIcon(iconRes: Int?) =
+ if (iconRes != null && iconRes != 0) {
+ Icon(painter = painterResource(iconRes), contentDescription = null)
+ } else {
+ null
+ }
+
+@Composable
+private fun AlertBodyText(body: String) =
+ Text(
+ text = body,
+ color = MaterialTheme.colors.onBackground,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.body2
+ )
+
+@Composable
+private fun PositiveButton(onClick: () -> Unit, contentDescription: String) =
+ Button(
+ imageVector = Icons.Default.Check,
+ contentDescription = contentDescription,
+ onClick = onClick
+ )
+
+@Composable
+private fun NegativeButton(onClick: () -> Unit, contentDescription: String) =
+ Button(
+ imageVector = Icons.Default.Close,
+ contentDescription = contentDescription,
+ onClick = onClick,
+ colors = ButtonDefaults.secondaryButtonColors()
+ )
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Button.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Button.kt
new file mode 100644
index 000000000..2e90f3356
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Button.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.Dp
+import androidx.wear.compose.material.Button
+import androidx.wear.compose.material.ButtonColors
+import androidx.wear.compose.material.ButtonDefaults
+import androidx.wear.compose.material.ButtonDefaults.DefaultButtonSize
+import androidx.wear.compose.material.ButtonDefaults.DefaultIconSize
+import androidx.wear.compose.material.ButtonDefaults.LargeButtonSize
+import androidx.wear.compose.material.ButtonDefaults.LargeIconSize
+import androidx.wear.compose.material.ButtonDefaults.SmallButtonSize
+import androidx.wear.compose.material.ButtonDefaults.SmallIconSize
+
+/**
+ * This component is an alternative to [Button], providing the following:
+ * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
+ * by the Wear guidelines;
+ */
+@Composable
+public fun Button(
+ imageVector: ImageVector,
+ contentDescription: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+ buttonSize: ButtonSize = ButtonSize.Default,
+ iconRtlMode: IconRtlMode = IconRtlMode.Default,
+ enabled: Boolean = true
+) {
+ Button(
+ icon = imageVector,
+ contentDescription = contentDescription,
+ onClick = onClick,
+ modifier = modifier,
+ colors = colors,
+ buttonSize = buttonSize,
+ iconRtlMode = iconRtlMode,
+ enabled = enabled
+ )
+}
+
+/**
+ * This component is an alternative to [Button], providing the following:
+ * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
+ * by the Wear guidelines;
+ */
+@Composable
+public fun Button(
+ @DrawableRes id: Int,
+ contentDescription: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+ buttonSize: ButtonSize = ButtonSize.Default,
+ iconRtlMode: IconRtlMode = IconRtlMode.Default,
+ enabled: Boolean = true
+) {
+ Button(
+ icon = id,
+ contentDescription = contentDescription,
+ onClick = onClick,
+ modifier = modifier,
+ colors = colors,
+ buttonSize = buttonSize,
+ iconRtlMode = iconRtlMode,
+ enabled = enabled
+ )
+}
+
+@Composable
+internal fun Button(
+ icon: Any,
+ contentDescription: String,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+ buttonSize: ButtonSize = ButtonSize.Default,
+ iconRtlMode: IconRtlMode = IconRtlMode.Default,
+ enabled: Boolean = true
+) {
+ Button(
+ onClick = onClick,
+ modifier = modifier.size(buttonSize.tapTargetSize),
+ enabled = enabled,
+ colors = colors
+ ) {
+ val iconModifier = Modifier
+ .size(buttonSize.iconSize)
+ .align(Alignment.Center)
+
+ Icon(
+ icon = icon,
+ contentDescription = contentDescription,
+ modifier = iconModifier,
+ rtlMode = iconRtlMode
+ )
+ }
+}
+
+public sealed class ButtonSize(
+ public val iconSize: Dp,
+ public val tapTargetSize: Dp
+) {
+ public object Default :
+ ButtonSize(iconSize = DefaultIconSize, tapTargetSize = DefaultButtonSize)
+
+ public object Large : ButtonSize(iconSize = LargeIconSize, tapTargetSize = LargeButtonSize)
+ public object Small : ButtonSize(iconSize = SmallIconSize, tapTargetSize = SmallButtonSize)
+
+ /**
+ * Custom sizes should follow the [accessibility principles and guidance for touch targets](https://developer.android.com/training/wearables/accessibility#set-minimum).
+ */
+ public data class Custom(val customIconSize: Dp, val customTapTargetSize: Dp) :
+ ButtonSize(iconSize = customIconSize, tapTargetSize = customTapTargetSize)
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt
new file mode 100644
index 000000000..ead1c2345
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import android.graphics.drawable.Drawable
+import androidx.annotation.StringRes
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.Chip
+import androidx.wear.compose.material.ChipColors
+import androidx.wear.compose.material.ChipDefaults
+import androidx.wear.compose.material.ContentAlpha
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import androidx.wear.compose.material.contentColorFor
+import com.android.permissioncontroller.R
+
+/**
+ * This component is an alternative to [Chip], providing the following:
+ * - a convenient way of providing a label and a secondary label;
+ * - a convenient way of providing an icon, and choosing their size based on the
+ * sizes recommended by the Wear guidelines;
+ */
+@Composable
+public fun Chip(
+ label: String,
+ labelMaxLines: Int? = null,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ secondaryLabel: String? = null,
+ secondaryLabelMaxLines: Int? = null,
+ icon: Any? = null,
+ iconContentDescription: String? = null,
+ largeIcon: Boolean = false,
+ textColor: Color = MaterialTheme.colors.onSurface,
+ iconColor: Color = Color.Unspecified,
+ colors: ChipColors = chipDefaultColors(),
+ enabled: Boolean = true
+) {
+ val iconParam: (@Composable BoxScope.() -> Unit)? =
+ icon?.let {
+ {
+ val iconSize = if (largeIcon) {
+ ChipDefaults.LargeIconSize
+ } else {
+ ChipDefaults.IconSize
+ }
+
+ Row {
+ val iconModifier = Modifier
+ .size(iconSize)
+ .clip(CircleShape)
+ when (icon) {
+ is ImageVector ->
+ Icon(
+ imageVector = icon,
+ tint = iconColor,
+ contentDescription = iconContentDescription,
+ modifier = iconModifier
+ )
+
+ is Int ->
+ Icon(
+ painter = painterResource(id = icon),
+ tint = iconColor,
+ contentDescription = iconContentDescription,
+ modifier = iconModifier
+ )
+ is Drawable ->
+ Icon(
+ painter = rememberDrawablePainter(icon),
+ tint = iconColor,
+ contentDescription = iconContentDescription,
+ modifier = iconModifier
+ )
+ else -> {
+ }
+ }
+ }
+ }
+ }
+
+ Chip(
+ label = label,
+ labelMaxLines = labelMaxLines,
+ onClick = onClick,
+ modifier = modifier,
+ secondaryLabel = secondaryLabel,
+ secondaryLabelMaxLines = secondaryLabelMaxLines,
+ icon = iconParam,
+ largeIcon = largeIcon,
+ textColor = textColor,
+ colors = colors,
+ enabled = enabled
+ )
+}
+
+/**
+ * This component is an alternative to [Chip], providing the following:
+ * - a convenient way of providing a label and a secondary label;
+ * - a convenient way of providing an icon, and choosing their size based on the
+ * sizes recommended by the Wear guidelines;
+ */
+@Composable
+public fun Chip(
+ @StringRes labelId: Int,
+ labelMaxLines: Int? = null,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ @StringRes secondaryLabel: Int? = null,
+ secondaryLabelMaxLines: Int? = null,
+ icon: Any? = null,
+ largeIcon: Boolean = false,
+ textColor: Color = MaterialTheme.colors.onSurface,
+ iconColor: Color = Color.Unspecified,
+ colors: ChipColors = chipDefaultColors(),
+ enabled: Boolean = true
+) {
+ Chip(
+ label = stringResource(id = labelId),
+ labelMaxLines = labelMaxLines,
+ onClick = onClick,
+ modifier = modifier,
+ secondaryLabel = secondaryLabel?.let { stringResource(id = it) },
+ secondaryLabelMaxLines = secondaryLabelMaxLines,
+ icon = icon,
+ largeIcon = largeIcon,
+ textColor = textColor,
+ iconColor = iconColor,
+ colors = colors,
+ enabled = enabled
+ )
+}
+
+/**
+ * This component is an alternative to [Chip], providing the following:
+ * - a convenient way of providing a label and a secondary label;
+ */
+@Composable
+public fun Chip(
+ label: String,
+ labelMaxLines: Int? = null,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ secondaryLabel: String? = null,
+ secondaryLabelMaxLines: Int? = null,
+ icon: (@Composable BoxScope.() -> Unit)? = null,
+ largeIcon: Boolean = false,
+ textColor: Color = MaterialTheme.colors.onSurface,
+ secondaryTextColor: Color = colorResource(R.color.wear_material_gray_600),
+ colors: ChipColors = chipDefaultColors(),
+ enabled: Boolean = true
+) {
+ val hasSecondaryLabel = secondaryLabel != null
+ val hasIcon = icon != null
+
+ val labelParam: (@Composable RowScope.() -> Unit) =
+ {
+ Text(
+ text = label,
+ color = textColor,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = if (hasSecondaryLabel || hasIcon) TextAlign.Start else TextAlign.Center,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = labelMaxLines ?: if (hasSecondaryLabel) 1 else 2,
+ style = MaterialTheme.typography.button
+ )
+ }
+
+ val secondaryLabelParam: (@Composable RowScope.() -> Unit)? =
+ secondaryLabel?.let {
+ {
+ Text(
+ text = secondaryLabel,
+ color = secondaryTextColor,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = secondaryLabelMaxLines ?: 1,
+ style = MaterialTheme.typography.caption2
+ )
+ }
+ }
+
+ val contentPadding = if (largeIcon) {
+ val verticalPadding = ChipDefaults.ChipVerticalPadding
+ PaddingValues(
+ start = 10.dp,
+ top = verticalPadding,
+ end = ChipDefaults.ChipHorizontalPadding,
+ bottom = verticalPadding
+ )
+ } else {
+ ChipDefaults.ContentPadding
+ }
+
+ Chip(
+ label = labelParam,
+ onClick = onClick,
+ modifier = modifier
+ .adjustChipHeightToFontScale(LocalConfiguration.current.fontScale)
+ .fillMaxWidth(),
+ secondaryLabel = secondaryLabelParam,
+ icon = icon,
+ colors = colors,
+ enabled = enabled,
+ contentPadding = contentPadding
+ )
+}
+
+/**
+ * Default colors of a Chip.
+ */
+@Composable
+fun chipDefaultColors(): ChipColors =
+ ChipDefaults.secondaryChipColors()
+
+/**
+ * ChipColors that disabled alpha is applied based on [ChipDefaults.secondaryChipColors()].
+ * It is used for a Chip which would like to respond to click events,
+ * meanwhile it seems disabled.
+ */
+@Composable
+fun chipDisabledColors(): ChipColors {
+ val backgroundColor = MaterialTheme.colors.surface
+ val contentColor = contentColorFor(backgroundColor)
+ val secondaryContentColor = contentColor
+ val iconColor = contentColor
+
+ return ChipDefaults.chipColors(
+ backgroundColor = backgroundColor.copy(alpha = ContentAlpha.disabled),
+ contentColor = contentColor.copy(alpha = ContentAlpha.disabled),
+ secondaryContentColor = secondaryContentColor.copy(alpha = ContentAlpha.disabled),
+ iconColor = iconColor.copy(alpha = ContentAlpha.disabled)
+ )
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt
new file mode 100644
index 000000000..28e7be022
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import android.graphics.drawable.Animatable
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.Drawable
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.view.View
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.RememberObserver
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.asAndroidColorFilter
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
+import androidx.compose.ui.graphics.nativeCanvas
+import androidx.compose.ui.graphics.painter.ColorPainter
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.withSave
+import androidx.compose.ui.unit.LayoutDirection
+import kotlin.math.roundToInt
+
+private val MAIN_HANDLER by lazy(LazyThreadSafetyMode.NONE) {
+ Handler(Looper.getMainLooper())
+}
+
+/**
+ * A [Painter] which draws an Android [Drawable] and supports [Animatable] drawables. Instances
+ * should be remembered to be able to start and stop [Animatable] animations.
+ *
+ * Instances are usually retrieved from [rememberDrawablePainter].
+ */
+class DrawablePainter(
+ val drawable: Drawable
+) : Painter(), RememberObserver {
+ private var drawInvalidateTick by mutableStateOf(0)
+ private var drawableIntrinsicSize by mutableStateOf(drawable.intrinsicSize)
+
+ private val callback: Drawable.Callback by lazy {
+ object : Drawable.Callback {
+ override fun invalidateDrawable(d: Drawable) {
+ // Update the tick so that we get re-drawn
+ drawInvalidateTick++
+ // Update our intrinsic size too
+ drawableIntrinsicSize = drawable.intrinsicSize
+ }
+
+ override fun scheduleDrawable(d: Drawable, what: Runnable, time: Long) {
+ MAIN_HANDLER.postAtTime(what, time)
+ }
+
+ override fun unscheduleDrawable(d: Drawable, what: Runnable) {
+ MAIN_HANDLER.removeCallbacks(what)
+ }
+ }
+ }
+
+ init {
+ if (drawable.intrinsicWidth >= 0 && drawable.intrinsicHeight >= 0) {
+ // Update the drawable's bounds to match the intrinsic size
+ drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
+ }
+ }
+
+ override fun onRemembered() {
+ drawable.callback = callback
+ drawable.setVisible(true, true)
+ if (drawable is Animatable) drawable.start()
+ }
+
+ override fun onAbandoned() = onForgotten()
+
+ override fun onForgotten() {
+ if (drawable is Animatable) drawable.stop()
+ drawable.setVisible(false, false)
+ drawable.callback = null
+ }
+
+ override fun applyAlpha(alpha: Float): Boolean {
+ drawable.alpha = (alpha * 255).roundToInt().coerceIn(0, 255)
+ return true
+ }
+
+ override fun applyColorFilter(colorFilter: ColorFilter?): Boolean {
+ drawable.colorFilter = colorFilter?.asAndroidColorFilter()
+ return true
+ }
+
+ override fun applyLayoutDirection(layoutDirection: LayoutDirection): Boolean {
+ if (Build.VERSION.SDK_INT >= 23) {
+ return drawable.setLayoutDirection(
+ when (layoutDirection) {
+ LayoutDirection.Ltr -> View.LAYOUT_DIRECTION_LTR
+ LayoutDirection.Rtl -> View.LAYOUT_DIRECTION_RTL
+ }
+ )
+ }
+ return false
+ }
+
+ override val intrinsicSize: Size get() = drawableIntrinsicSize
+
+ override fun DrawScope.onDraw() {
+ drawIntoCanvas { canvas ->
+ // Reading this ensures that we invalidate when invalidateDrawable() is called
+ drawInvalidateTick
+
+ // Update the Drawable's bounds
+ drawable.setBounds(0, 0, size.width.roundToInt(), size.height.roundToInt())
+
+ canvas.withSave {
+ drawable.draw(canvas.nativeCanvas)
+ }
+ }
+ }
+}
+
+/**
+ * Remembers [Drawable] wrapped up as a [Painter]. This function attempts to un-wrap the
+ * drawable contents and use Compose primitives where possible.
+ *
+ * If the provided [drawable] is `null`, an empty no-op painter is returned.
+ *
+ * This function tries to dispatch lifecycle events to [drawable] as much as possible from
+ * within Compose.
+ */
+@Composable
+fun rememberDrawablePainter(drawable: Drawable?): Painter = remember(drawable) {
+ when (drawable) {
+ null -> EmptyPainter
+ is ColorDrawable -> ColorPainter(Color(drawable.color))
+ // Since the DrawablePainter will be remembered and it implements RememberObserver, it
+ // will receive the necessary events
+ else -> DrawablePainter(drawable.mutate())
+ }
+}
+
+private val Drawable.intrinsicSize: Size
+ get() = when {
+ // Only return a finite size if the drawable has an intrinsic size
+ intrinsicWidth >= 0 && intrinsicHeight >= 0 -> {
+ Size(width = intrinsicWidth.toFloat(), height = intrinsicHeight.toFloat())
+ }
+ else -> Size.Unspecified
+ }
+
+internal object EmptyPainter : Painter() {
+ override val intrinsicSize: Size get() = Size.Unspecified
+ override fun DrawScope.onDraw() {}
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Icon.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Icon.kt
new file mode 100644
index 000000000..a71a5a403
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Icon.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import android.graphics.drawable.Drawable
+import androidx.annotation.DrawableRes
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.scale
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.LocalContentAlpha
+import androidx.wear.compose.material.LocalContentColor
+
+/**
+ * This component is an alternative to [Icon], providing the following:
+ * - a convenient way of setting the icon to be mirrored in RTL mode;
+ */
+@Composable
+public fun Icon(
+ imageVector: ImageVector,
+ contentDescription: String?,
+ modifier: Modifier = Modifier,
+ tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+ rtlMode: IconRtlMode = IconRtlMode.Default
+) {
+ val shouldMirror =
+ rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+ Icon(
+ modifier = modifier.scale(
+ scaleX = if (shouldMirror) -1f else 1f,
+ scaleY = 1f
+ ),
+ imageVector = imageVector,
+ contentDescription = contentDescription,
+ tint = tint
+ )
+}
+
+/**
+ * This component is an alternative to [Icon], providing the following:
+ * - a convenient way of setting the icon to be mirrored in RTL mode;
+ */
+@Composable
+public fun Icon(
+ @DrawableRes id: Int,
+ contentDescription: String?,
+ modifier: Modifier = Modifier,
+ tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+ rtlMode: IconRtlMode = IconRtlMode.Default
+) {
+ val shouldMirror =
+ rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+
+ Icon(
+ painter = painterResource(id = id),
+ contentDescription = contentDescription,
+ modifier = modifier.scale(
+ scaleX = if (shouldMirror) -1f else 1f,
+ scaleY = 1f
+ ),
+ tint = tint
+ )
+}
+
+/**
+ * This component is an alternative to [Icon], providing the following:
+ * - a convenient way of providing an icon of various types
+ * - a convenient way of setting the icon to be mirrored in RTL mode;
+ */
+@Composable
+fun Icon(
+ icon: Any,
+ contentDescription: String?,
+ modifier: Modifier = Modifier,
+ tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+ rtlMode: IconRtlMode = IconRtlMode.Default
+) {
+ val shouldMirror =
+ rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+
+ val iconModifier = modifier.scale(
+ scaleX = if (shouldMirror) -1f else 1f,
+ scaleY = 1f
+ )
+ when (icon) {
+ is ImageVector -> {
+ Icon(
+ imageVector = icon,
+ modifier = iconModifier,
+ contentDescription = contentDescription,
+ tint = tint
+ )
+ }
+
+ is Int -> {
+ Icon(
+ painter = painterResource(id = icon),
+ contentDescription = contentDescription,
+ modifier = iconModifier,
+ tint = tint
+ )
+ }
+
+ is Drawable -> {
+ Icon(
+ painter = rememberDrawablePainter(icon),
+ contentDescription = contentDescription,
+ modifier = iconModifier,
+ tint = tint
+ )
+ }
+
+ else -> throw IllegalArgumentException("Type not supported.")
+ }
+}
+
+public enum class IconRtlMode {
+ Default,
+ Mirrored
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListFooter.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListFooter.kt
new file mode 100644
index 000000000..3d668ca02
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListFooter.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+
+/**
+ * A slot based composable for creating a list footer item.
+ */
+@Composable
+fun ListFooter(
+ description: String,
+ iconRes: Int? = null,
+ onClick: (() -> Unit)? = null
+) {
+ val modifier = Modifier.fillMaxWidth()
+ Row(
+ modifier = if (onClick == null) {
+ modifier
+ } else {
+ modifier.clickable(onClick = onClick)
+ }
+ ) {
+ iconRes?.let {
+ Spacer(modifier = Modifier.width(LeadingIconStartSpacing))
+ Icon(
+ painter = painterResource(id = it),
+ contentDescription = null,
+ modifier = Modifier
+ .size(LeadingIconSize, LeadingIconSize)
+ .align(Alignment.CenterVertically)
+ )
+ Spacer(modifier = Modifier.width(LeadingIconEndSpacing))
+ }
+ Text(
+ text = description,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Start,
+ overflow = TextOverflow.Ellipsis,
+ color = MaterialTheme.colors.onSurfaceVariant,
+ style = MaterialTheme.typography.caption2
+ )
+ }
+}
+
+/**
+ * The size of the spacing before the leading icon when they used inside a list footer.
+ */
+private val LeadingIconStartSpacing = 4.dp
+
+/**
+ * The size of the spacing between the leading icon and a text inside a list footer.
+ */
+private val LeadingIconEndSpacing = 8.dp
+
+/**
+ * The size of the leading icon.
+ */
+private val LeadingIconSize = 24.dp
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
new file mode 100644
index 000000000..93ba3ca49
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.semantics.heading
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.LocalContentColor
+import androidx.wear.compose.material.LocalTextStyle
+
+/**
+ * A slot based composable for creating a list header item. [ListHeader]s are typically expected
+ * to be a few words of text on a single line.
+ * The contents will be start and end padded.
+ *
+ * @param modifier The modifier for the [ListHeader].
+ * @param backgroundColor The background color to apply - typically Color.Transparent
+ * @param contentColor The color to apply to content.
+ * @param contentPadding The spacing values to apply internally between the container
+ * and the content.
+ * @param content Slot for [ListHeader] content, expected to be a single line of text.
+ */
+@Composable
+fun ListHeader(
+ modifier: Modifier = Modifier,
+ backgroundColor: Color = Color.Transparent,
+ contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
+ contentPadding: PaddingValues = ListHeaderDefaults.HeaderContentPadding,
+ content: @Composable RowScope.() -> Unit
+) {
+ Row(
+ horizontalArrangement = Arrangement.Center,
+ modifier = modifier
+ .defaultMinSize(minHeight = ListHeaderDefaults.Height)
+ .height(IntrinsicSize.Min)
+ .wrapContentSize()
+ .background(backgroundColor)
+ .padding(contentPadding)
+ .semantics(mergeDescendants = true) { heading() }
+ ) {
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
+ LocalTextStyle provides MaterialTheme.typography.title3,
+ ) {
+ content()
+ }
+ }
+}
+
+/**
+ * A two slot based composable for creating a list subheader item.
+ * [ListSubheader]s offer slots for an icon and for a text label.
+ * The contents will be start and end padded.
+ *
+ * @param modifier The modifier for the [ListSubheader].
+ * @param backgroundColor The background color to apply - typically Color.Transparent
+ * @param contentColor The color to apply to content.
+ * @param contentPadding The spacing values to apply internally between the container
+ * and the content.
+ * @param icon A slot for providing icon to the [ListSubheader].
+ * @param label A slot for providing label to the [ListSubheader].
+ */
+@Composable
+fun ListSubheader(
+ modifier: Modifier = Modifier,
+ backgroundColor: Color = Color.Transparent,
+ contentColor: Color = MaterialTheme.colors.onBackground,
+ contentPadding: PaddingValues = ListHeaderDefaults.SubheaderContentPadding,
+ icon: (@Composable BoxScope.() -> Unit)? = null,
+ label: @Composable RowScope.() -> Unit,
+) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.Start,
+ modifier = modifier
+ .defaultMinSize(minHeight = ListHeaderDefaults.Height)
+ .height(IntrinsicSize.Min)
+ .fillMaxWidth()
+ .wrapContentSize(align = Alignment.CenterStart)
+ .background(backgroundColor)
+ .padding(contentPadding)
+ .semantics(mergeDescendants = true) { heading() }
+ ) {
+ CompositionLocalProvider(
+ LocalContentColor provides contentColor,
+ LocalTextStyle provides MaterialTheme.typography.caption1,
+ ) {
+ if (icon != null) {
+ Box(
+ modifier = Modifier.wrapContentSize(align = Alignment.CenterStart),
+ content = icon
+ )
+ Spacer(modifier = Modifier.width(6.dp))
+ }
+ label()
+ }
+ }
+}
+
+object ListHeaderDefaults {
+ private val TopPadding = 16.dp
+ private val SubheaderBottomPadding = 8.dp
+ private val HeaderBottomPadding = 12.dp
+ private val HorizontalPadding = 14.dp
+ internal val Height = 48.dp
+
+ val HeaderContentPadding = PaddingValues(
+ HorizontalPadding,
+ TopPadding,
+ HorizontalPadding,
+ HeaderBottomPadding
+ )
+ val SubheaderContentPadding = PaddingValues(
+ HorizontalPadding,
+ TopPadding,
+ HorizontalPadding,
+ SubheaderBottomPadding
+ )
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
new file mode 100644
index 000000000..758dc71d9
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import android.graphics.drawable.Drawable
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.gestures.scrollBy
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.input.rotary.onRotaryScrollEvent
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
+import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.material.CircularProgressIndicator
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.PositionIndicator
+import androidx.wear.compose.material.Scaffold
+import androidx.wear.compose.material.Text
+import androidx.wear.compose.material.TimeText
+import androidx.wear.compose.material.Vignette
+import androidx.wear.compose.material.VignettePosition
+import androidx.wear.compose.material.scrollAway
+import kotlinx.coroutines.launch
+
+/**
+ * Screen that contains a list of items defined using the [content] parameter, adds the time text
+ * (if [showTimeText] is true), the tile (if [title] is not null), the vignette and the position
+ * indicator. It also manages the scaling animation and allows the user to scroll the content using
+ * the crown.
+ */
+@Composable
+fun ScrollableScreen(
+ showTimeText: Boolean = true,
+ title: String? = null,
+ subtitle: String? = null,
+ image: Any? = null,
+ isLoading: Boolean = false,
+ content: ScalingLazyListScope.() -> Unit,
+) {
+ val focusRequester = remember { FocusRequester() }
+ val listState = remember { ScalingLazyListState(initialCenterItemIndex = 0) }
+ val coroutineScope = rememberCoroutineScope()
+
+ MaterialTheme {
+ Scaffold(
+ modifier = Modifier.onRotaryScrollEvent {
+ coroutineScope.launch {
+ listState.scrollBy(it.verticalScrollPixels)
+ }
+ true
+ }
+ .focusRequester(focusRequester)
+ .focusable(),
+ timeText = {
+ // TODO(b/302002254): Temperately skip broken library. Please revert back once
+ // b/300996348 is resolved.
+ if (false && showTimeText && !isLoading) {
+ TimeText(
+ modifier = Modifier.scrollAway(listState),
+ contentPadding = PaddingValues(15.dp)
+ )
+ }
+ },
+ vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) },
+ positionIndicator = { PositionIndicator(scalingLazyListState = listState) }
+ ) {
+ Box(modifier = Modifier.fillMaxSize()) {
+ if (isLoading) {
+ CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
+ } else {
+ ScalingLazyColumn(
+ state = listState,
+ // Set autoCentering to null to avoid adding extra padding based on the content.
+ autoCentering = null,
+ contentPadding = PaddingValues(
+ start = 10.dp,
+ end = 10.dp,
+ top = 32.dp,
+ bottom = 70.dp
+ )
+ ) {
+ image?.let {
+ when (image) {
+ is Int ->
+ item {
+ Image(
+ painter = painterResource(id = image),
+ contentDescription = null
+ )
+ }
+ is Drawable ->
+ item {
+ Image(
+ painter = rememberDrawablePainter(image),
+ contentDescription = null
+ )
+ }
+ else -> {
+ }
+ }
+ }
+ if (title != null) {
+ item {
+ ListHeader {
+ Text(text = title, textAlign = TextAlign.Center)
+ }
+ }
+ }
+ if (subtitle != null) {
+ item {
+ Text(
+ text = subtitle,
+ style = MaterialTheme.typography.body2,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center
+ )
+ }
+ }
+
+ content()
+ }
+ RequestFocusOnResume(focusRequester = focusRequester)
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun RequestFocusOnResume(focusRequester: FocusRequester) {
+ val lifecycleOwner = LocalLifecycleOwner.current
+ LaunchedEffect(Unit) {
+ lifecycleOwner.repeatOnLifecycle(state = Lifecycle.State.RESUMED) {
+ focusRequester.requestFocus()
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
new file mode 100644
index 000000000..90bc42caf
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.stateDescription
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.wear.compose.material.contentColorFor
+import androidx.wear.compose.material.ChipDefaults
+import androidx.wear.compose.material.ContentAlpha
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import androidx.wear.compose.material.ToggleChip
+import androidx.wear.compose.material.ToggleChipColors
+import androidx.wear.compose.material.ToggleChipDefaults
+import com.android.permissioncontroller.R
+
+/**
+ * This component is an alternative to [ToggleChip], providing the following:
+ * - a convenient way of providing a label and a secondary label;
+ * - a convenient way of choosing the toggle control;
+ * - a convenient way of providing an icon and setting the icon to be mirrored in RTL mode;
+ */
+@Composable
+public fun ToggleChip(
+ checked: Boolean,
+ onCheckedChanged: (Boolean) -> Unit,
+ label: String,
+ labelMaxLine: Int? = null,
+ toggleControl: ToggleChipToggleControl,
+ modifier: Modifier = Modifier,
+ icon: Any? = null,
+ iconColor: Color = Color.Unspecified,
+ iconRtlMode: IconRtlMode = IconRtlMode.Default,
+ secondaryLabel: String? = null,
+ secondaryLabelMaxLine: Int? = null,
+ colors: ToggleChipColors = ToggleChipDefaults.toggleChipColors(),
+ enabled: Boolean = true,
+ interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
+) {
+ val hasSecondaryLabel = secondaryLabel != null
+
+ val labelParam: (@Composable RowScope.() -> Unit) =
+ {
+ Text(
+ text = label,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Start,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = labelMaxLine ?: if (hasSecondaryLabel) 1 else 2,
+ style = MaterialTheme.typography.button
+ )
+ }
+
+ val secondaryLabelParam: (@Composable RowScope.() -> Unit)? =
+ secondaryLabel?.let {
+ {
+ Text(
+ text = secondaryLabel,
+ overflow = TextOverflow.Ellipsis,
+ maxLines = secondaryLabelMaxLine ?: 1,
+ style = MaterialTheme.typography.caption2
+ )
+ }
+ }
+
+ val toggleControlParam: (@Composable () -> Unit) = {
+ Icon(
+ imageVector = when (toggleControl) {
+ ToggleChipToggleControl.Switch -> ToggleChipDefaults.switchIcon(checked)
+ ToggleChipToggleControl.Radio -> ToggleChipDefaults.radioIcon(checked)
+ ToggleChipToggleControl.Checkbox -> ToggleChipDefaults.checkboxIcon(checked)
+ },
+ contentDescription = null,
+ // This potentially be removed once this issue is addressed:
+ // https://issuetracker.google.com/issues/287087138
+ rtlMode = if (toggleControl == ToggleChipToggleControl.Switch) {
+ IconRtlMode.Mirrored
+ } else {
+ IconRtlMode.Default
+ }
+ )
+ }
+
+ val iconParam: (@Composable BoxScope.() -> Unit)? =
+ icon?.let {
+ {
+ Row {
+ Icon(
+ icon = icon,
+ tint = iconColor,
+ contentDescription = null,
+ modifier = Modifier
+ .size(ChipDefaults.IconSize)
+ .clip(CircleShape),
+ rtlMode = iconRtlMode
+ )
+ }
+ }
+ }
+
+ val stateDescriptionSemantics = stringResource(
+ if (checked) {
+ R.string.on
+ } else {
+ R.string.off
+ }
+ )
+ ToggleChip(
+ checked = checked,
+ onCheckedChange = onCheckedChanged,
+ label = labelParam,
+ toggleControl = toggleControlParam,
+ modifier = modifier
+ .adjustChipHeightToFontScale(LocalConfiguration.current.fontScale)
+ .fillMaxWidth()
+ .semantics {
+ stateDescription = stateDescriptionSemantics
+ },
+ appIcon = iconParam,
+ secondaryLabel = secondaryLabelParam,
+ colors = colors,
+ enabled = enabled,
+ interactionSource = interactionSource
+ )
+}
+
+/**
+ * ToggleChipColors that disabled alpha is applied based on [ToggleChipDefaults.toggleChipColors()].
+ * It is used for a ToggleChip which would like to respond to click events,
+ * meanwhile it seems disabled.
+ */
+@Composable
+fun toggleChipDisabledColors(): ToggleChipColors {
+ val checkedStartBackgroundColor = MaterialTheme.colors.surface.copy(alpha = 0f)
+ .compositeOver(MaterialTheme.colors.surface)
+ val checkedEndBackgroundColor = MaterialTheme.colors.primary.copy(alpha = 0.5f)
+ .compositeOver(MaterialTheme.colors.surface)
+ val checkedContentColor = MaterialTheme.colors.onSurface
+ val checkedSecondaryContentColor = MaterialTheme.colors.onSurfaceVariant
+ val checkedToggleControlColor = MaterialTheme.colors.secondary
+ val uncheckedStartBackgroundColor = MaterialTheme.colors.surface
+ val uncheckedEndBackgroundColor = uncheckedStartBackgroundColor
+ val uncheckedContentColor = contentColorFor(checkedEndBackgroundColor)
+ val uncheckedSecondaryContentColor = uncheckedContentColor
+ val uncheckedToggleControlColor = uncheckedContentColor
+
+ return ToggleChipDefaults.toggleChipColors(
+ checkedStartBackgroundColor = checkedStartBackgroundColor
+ .copy(alpha = ContentAlpha.disabled),
+ checkedEndBackgroundColor = checkedEndBackgroundColor
+ .copy(alpha = ContentAlpha.disabled),
+ checkedContentColor = checkedContentColor
+ .copy(alpha = ContentAlpha.disabled),
+ checkedSecondaryContentColor = checkedSecondaryContentColor
+ .copy(alpha = ContentAlpha.disabled),
+ checkedToggleControlColor = checkedToggleControlColor
+ .copy(alpha = ContentAlpha.disabled),
+ uncheckedStartBackgroundColor = uncheckedStartBackgroundColor
+ .copy(alpha = ContentAlpha.disabled),
+ uncheckedEndBackgroundColor = uncheckedEndBackgroundColor
+ .copy(alpha = ContentAlpha.disabled),
+ uncheckedContentColor = uncheckedContentColor
+ .copy(alpha = ContentAlpha.disabled),
+ uncheckedSecondaryContentColor = uncheckedSecondaryContentColor
+ .copy(alpha = ContentAlpha.disabled),
+ uncheckedToggleControlColor = uncheckedToggleControlColor
+ .copy(alpha = ContentAlpha.disabled)
+ )
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChipToggleControl.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChipToggleControl.kt
new file mode 100644
index 000000000..e123ecb81
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChipToggleControl.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.wear.elements
+
+public enum class ToggleChipToggleControl {
+ Switch, Radio, Checkbox
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionConfirmDialogViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionConfirmDialogViewModel.kt
new file mode 100644
index 000000000..8da12d037
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionConfirmDialogViewModel.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.wear.model
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel
+import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs
+
+class AppPermissionConfirmDialogViewModel : ViewModel() {
+ /** A livedata which stores whether confirmation dialog is visible. */
+ val showConfirmDialogLiveData = MutableLiveData<Boolean>()
+
+ /** Arguments for a confirmation dialog. */
+ var confirmDialogArgs: ConfirmDialogArgs? = null
+
+ /** A livedata which stores whether confirmation dialog is visible. */
+ val showAdvancedConfirmDialogLiveData = MutableLiveData<Boolean>()
+
+ /** Arguments for an advanced confirmation dialog. */
+ var advancedConfirmDialogArgs: AdvancedConfirmDialogArgs? = null
+
+ init {
+ showConfirmDialogLiveData.value = false
+ showAdvancedConfirmDialogLiveData.value = false
+ }
+}
+
+/**
+ * Factory for an AppPermissionConfirmDialogViewModel
+ */
+class AppPermissionConfirmDialogViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return AppPermissionConfirmDialogViewModel() as T
+ }
+}
+
+/** */
+data class ConfirmDialogArgs(
+ val messageId: Int,
+ val changeRequest: AppPermissionViewModel.ChangeRequest,
+ val buttonPressed: Int,
+ val oneTime: Boolean
+) \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionGroupsRevokeDialogViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionGroupsRevokeDialogViewModel.kt
new file mode 100644
index 000000000..699591912
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/AppPermissionGroupsRevokeDialogViewModel.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 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.wear.model
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+class AppPermissionGroupsRevokeDialogViewModel : ViewModel() {
+ /** A livedata which stores whether the dialog is visible. */
+ val showDialogLiveData = MutableLiveData<Boolean>()
+ var hasConfirmedRevoke: Boolean = false
+ var revokeDialogArgs: RevokeDialogArgs? = null
+
+ init {
+ showDialogLiveData.value = false
+ }
+
+ fun dismissDialog() {
+ showDialogLiveData.value = false
+ revokeDialogArgs = null
+ }
+}
+
+/**
+ * Factory for an AppPermissionGroupsRevokeDialogViewModel
+ */
+class AppPermissionGroupsRevokeDialogViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return AppPermissionGroupsRevokeDialogViewModel() as T
+ }
+}
+
+data class RevokeDialogArgs(
+ val messageId: Int,
+ val onOkButtonClick: () -> Unit,
+ val onCancelButtonClick: () -> Unit
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearGrantPermissionsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearGrantPermissionsViewModel.kt
new file mode 100644
index 000000000..40680c64e
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearGrantPermissionsViewModel.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 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.wear.model
+
+import android.graphics.drawable.Drawable
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+class WearGrantPermissionsViewModel : ViewModel() {
+ /** A livedata which stores the permission group name. */
+ val groupNameLiveData = MutableLiveData<String>()
+
+ /** A livedata which stores the permission group icon. */
+ val iconLiveData = MutableLiveData<Drawable?>()
+
+ /** A livedata which stores the permission group message. */
+ val groupMessageLiveData = MutableLiveData<String>()
+
+ /** A livedata which stores the permission group detail message. */
+ val detailMessageLiveData = MutableLiveData<String?>()
+
+ /** A livedata which stores the permission group location-granularity visibilities. */
+ val locationVisibilitiesLiveData = MutableLiveData<List<Boolean>>()
+
+ /** A livedata which stores weather the precise location toggle chip is checked. */
+ val preciseLocationCheckedLiveData = MutableLiveData<Boolean>()
+
+ /** A livedata which stores the permission group button visibilities. */
+ val buttonVisibilitiesLiveData = MutableLiveData<List<Boolean>>()
+
+ init {
+ groupNameLiveData.value = ""
+ iconLiveData.value = null
+ groupMessageLiveData.value = ""
+ detailMessageLiveData.value = null
+ locationVisibilitiesLiveData.value = emptyList()
+ preciseLocationCheckedLiveData.value = false
+ buttonVisibilitiesLiveData.value = emptyList()
+ }
+}
+
+/**
+ * Factory for a WearGrantPermissionsViewModel
+ */
+class WearGrantPermissionsViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return WearGrantPermissionsViewModel() as T
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearUnusedAppsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearUnusedAppsViewModel.kt
new file mode 100644
index 000000000..38810ddd6
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearUnusedAppsViewModel.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.wear.model
+
+import android.graphics.drawable.Drawable
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod
+
+class WearUnusedAppsViewModel : ViewModel() {
+ /** A livedata which indicates if the loading animation should be showed. */
+ val loadingLiveData = MutableLiveData<Boolean>()
+
+ /** A livedata which stores unused period category visibilities. */
+ val unusedPeriodCategoryVisibilitiesLiveData = MutableLiveData<List<Boolean>>()
+
+ /** A livedata which indicates if the info massage category is visible or not. */
+ val infoMsgCategoryVisibilityLiveData = MutableLiveData<Boolean>()
+
+ /** A livedata which stores a map of unused apps group by UnusedPeriod. */
+ val unusedAppChipsLiveData =
+ MutableLiveData<MutableMap<UnusedPeriod, MutableMap<String, UnusedAppChip>>>()
+
+ data class UnusedAppChip(
+ val label: String,
+ val summary: String?,
+ val icon: Drawable?,
+ val contentDescription: String?,
+ val onClick: () -> Unit,
+ )
+
+ init {
+ loadingLiveData.value = true
+ unusedPeriodCategoryVisibilitiesLiveData.value = emptyList()
+ infoMsgCategoryVisibilityLiveData.value = false
+ unusedAppChipsLiveData.value = mutableMapOf()
+ }
+}
+
+/** Factory for a WearUnusedAppsViewModel */
+class WearUnusedAppsViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST") return WearUnusedAppsViewModel() as T
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/ContextCompat.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/ContextCompat.java
new file mode 100644
index 000000000..4ee23f7a0
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/ContextCompat.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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.utils;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.modules.utils.build.SdkLevel;
+
+/**
+ * Helper Context compat class for {@link Context}.
+ */
+public class ContextCompat {
+ /**
+ * The default device ID, which is the ID of the primary (non-virtual) device.
+ *
+ * @see Context#DEVICE_ID_DEFAULT
+ */
+ public static final int DEVICE_ID_DEFAULT = 0;
+
+ private ContextCompat() {
+ }
+
+ /**
+ * @return The default device ID for pre V platforms, otherwise returns the device ID from
+ * the context.
+ */
+ public static int getDeviceId(@NonNull Context context) {
+ if (SdkLevel.isAtLeastU()) {
+ return context.getDeviceId();
+ } else {
+ return DEVICE_ID_DEFAULT;
+ }
+
+ }
+
+ /**
+ * Creates a new device context, if needed.
+ *
+ * @return A new context if the input context is for a different device, otherwise
+ * return the same context object. See {@link Context#DEVICE_ID_DEFAULT}
+ */
+ @NonNull
+ public static Context createDeviceContext(@NonNull Context context, int deviceId) {
+ if (SdkLevel.isAtLeastU()) {
+ return deviceId == context.getDeviceId()
+ ? context : context.createDeviceContext(deviceId);
+ } else {
+ if (deviceId != DEVICE_ID_DEFAULT) {
+ throw new IllegalArgumentException("Invalid device ID " + deviceId);
+ }
+ return context;
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index 7db6e8669..ee0606610 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -74,6 +74,7 @@ import androidx.navigation.NavController
import androidx.preference.Preference
import androidx.preference.PreferenceGroup
import com.android.modules.utils.build.SdkLevel
+import com.android.permissioncontroller.Constants
import com.android.permissioncontroller.DeviceUtils
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.R
@@ -86,7 +87,7 @@ import com.android.permissioncontroller.permission.model.livedatatypes.LightPerm
import com.android.permissioncontroller.permission.model.livedatatypes.PermState
import com.android.permissioncontroller.permission.service.LocationAccessCheck
import com.android.permissioncontroller.permission.ui.handheld.SettingsWithLargeHeader
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import java.time.Duration
import java.util.concurrent.atomic.AtomicReference
import kotlin.coroutines.Continuation
@@ -98,7 +99,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
-
/**
* A set of util functions designed to work with kotlin, though they can work with java, as well.
*/
@@ -106,13 +106,14 @@ object KotlinUtils {
private const val LOG_TAG = "PermissionController Utils"
- private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK = FLAG_PERMISSION_USER_SET or
- FLAG_PERMISSION_USER_FIXED or
- FLAG_PERMISSION_ONE_TIME or
- FLAG_PERMISSION_REVOKED_COMPAT or
- FLAG_PERMISSION_ONE_TIME or
- FLAG_PERMISSION_REVIEW_REQUIRED or
- FLAG_PERMISSION_AUTO_REVOKED
+ private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK =
+ FLAG_PERMISSION_USER_SET or
+ FLAG_PERMISSION_USER_FIXED or
+ FLAG_PERMISSION_ONE_TIME or
+ FLAG_PERMISSION_REVOKED_COMPAT or
+ FLAG_PERMISSION_ONE_TIME or
+ FLAG_PERMISSION_REVIEW_REQUIRED or
+ FLAG_PERMISSION_AUTO_REVOKED
private const val KILL_REASON_APP_OP_CHANGE = "Permission related app op changed"
private const val SAFETY_PROTECTION_RESOURCES_ENABLED = "safety_protection_enabled"
@@ -131,30 +132,24 @@ object KotlinUtils {
private val ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE =
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE
- /** Whether to show the Permissions Hub. */
- private const val PROPERTY_PERMISSIONS_HUB_2_ENABLED = "permissions_hub_2_enabled"
-
- /** Whether to show the mic and camera icons. */
+ /** Whether to show the mic and camera icons. */
private const val PROPERTY_CAMERA_MIC_ICONS_ENABLED = "camera_mic_icons_enabled"
/** Whether to show the location indicators. */
private const val PROPERTY_LOCATION_INDICATORS_ENABLED = "location_indicators_enabled"
- /** Whether location accuracy feature is enabled */
- private const val PROPERTY_LOCATION_ACCURACY_ENABLED = "location_accuracy_enabled"
-
- /** Whether to show 7-day toggle in privacy hub. */
+ /** Whether to show 7-day toggle in privacy hub. */
private const val PRIVACY_DASHBOARD_7_DAY_TOGGLE = "privacy_dashboard_7_day_toggle"
/** Default location precision */
private const val PROPERTY_LOCATION_PRECISION = "location_precision"
- /** Whether to show the photo picker option in permission prompts. */
+ /** Whether to show the photo picker option in permission prompts. */
private const val PROPERTY_PHOTO_PICKER_PROMPT_ENABLED = "photo_picker_prompt_enabled"
/**
- * The minimum amount of time to wait, after scheduling the safety label changes job, before
- * the job actually runs for the first time.
+ * The minimum amount of time to wait, after scheduling the safety label changes job, before the
+ * job actually runs for the first time.
*/
private const val PROPERTY_SAFETY_LABEL_CHANGES_JOB_DELAY_MILLIS =
"safety_label_changes_job_delay_millis"
@@ -171,85 +166,50 @@ object KotlinUtils {
private const val PROPERTY_SAFETY_LABEL_CHANGES_JOB_SERVICE_KILL_SWITCH =
"safety_label_changes_job_service_kill_switch"
- /**
- * Whether the Permissions Hub 2 flag is enabled
- *
- * @return whether the flag is enabled
- */
- @ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
- fun isPermissionsHub2FlagEnabled(): Boolean {
- return SdkLevel.isAtLeastS() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_2_ENABLED, false)
- }
- /**
- * Whether to show the Permissions Dashboard
- *
- * @return whether to show the Permissions Dashboard.
- */
- @ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
- fun shouldShowPermissionsDashboard(): Boolean {
- return isPermissionsHub2FlagEnabled()
- }
-
- /**
- * Whether the Camera and Mic Icons are enabled by flag.
- *
- * @return whether the Camera and Mic Icons are enabled.
- */
- @ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
- fun isCameraMicIconsFlagEnabled(): Boolean {
- return SdkLevel.isAtLeastS() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_CAMERA_MIC_ICONS_ENABLED, true)
- }
+ private const val PROPERTY_NEW_GRANT_DIALOG_BACKEND = "new_grand_dialog_backend"
/**
- * Whether to show Camera and Mic Icons. They should be shown if the permission hub, or the icons
- * specifically, are enabled.
+ * Whether to show Camera and Mic Icons.
*
* @return whether to show the icons.
*/
@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
fun shouldShowCameraMicIndicators(): Boolean {
- return isCameraMicIconsFlagEnabled() || isPermissionsHub2FlagEnabled()
- }
-
- /**
- * Whether the location indicators are enabled by flag.
- *
- * @return whether the location indicators are enabled by flag.
- */
- @ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
- fun isLocationIndicatorsFlagEnabled(): Boolean {
- return SdkLevel.isAtLeastS() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_INDICATORS_ENABLED, false)
+ return SdkLevel.isAtLeastS() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_CAMERA_MIC_ICONS_ENABLED,
+ true
+ )
}
/**
- * Whether to show the location indicators. The location indicators are enable if the
- * permission hub, or location indicator specifically are enabled.
+ * Whether to show the location indicators.
*/
@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
fun shouldShowLocationIndicators(): Boolean {
- return isLocationIndicatorsFlagEnabled() || isPermissionsHub2FlagEnabled()
+ return SdkLevel.isAtLeastS() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_LOCATION_INDICATORS_ENABLED,
+ false
+ )
}
- /**
- * Whether the location accuracy feature is enabled
- */
+ /** Whether the location accuracy feature is enabled */
@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
fun isLocationAccuracyEnabled(): Boolean {
- return SdkLevel.isAtLeastS() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_ACCURACY_ENABLED, true)
+ return SdkLevel.isAtLeastS()
}
- /**
- * Default state of location precision
- * true: default is FINE.
- * false: default is COARSE.
- */
+ /** Default state of location precision true: default is FINE. false: default is COARSE. */
fun getDefaultPrecision(): Boolean {
- return !SdkLevel.isAtLeastS() || DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_LOCATION_PRECISION, true)
+ return !SdkLevel.isAtLeastS() ||
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_LOCATION_PRECISION,
+ true
+ )
}
/**
@@ -259,8 +219,12 @@ object KotlinUtils {
*/
@ChecksSdkIntAtLeast(Build.VERSION_CODES.S)
fun is7DayToggleEnabled(): Boolean {
- return SdkLevel.isAtLeastS() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PRIVACY_DASHBOARD_7_DAY_TOGGLE, false)
+ return SdkLevel.isAtLeastS() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PRIVACY_DASHBOARD_7_DAY_TOGGLE,
+ false
+ )
}
/**
@@ -270,11 +234,25 @@ object KotlinUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isPhotoPickerPromptEnabled(): Boolean {
+ return isPhotoPickerPromptSupported() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_PHOTO_PICKER_PROMPT_ENABLED,
+ true
+ )
+ }
+
+ /**
+ * Whether the Photo Picker Prompt is supported by the device
+ *
+ */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
+ fun isPhotoPickerPromptSupported(): Boolean {
val app = PermissionControllerApplication.get()
- return SdkLevel.isAtLeastU() && !DeviceUtils.isAuto(app) &&
- !DeviceUtils.isTelevision(app) && !DeviceUtils.isWear(app) &&
- DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_PHOTO_PICKER_PROMPT_ENABLED, true)
+ return SdkLevel.isAtLeastU() &&
+ !DeviceUtils.isAuto(app) &&
+ !DeviceUtils.isTelevision(app) &&
+ !DeviceUtils.isWear(app)
}
/*
@@ -284,8 +262,12 @@ object KotlinUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isPermissionRationaleEnabled(): Boolean {
- return SdkLevel.isAtLeastU() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PERMISSION_RATIONALE_ENABLED, true)
+ return SdkLevel.isAtLeastU() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PERMISSION_RATIONALE_ENABLED,
+ true
+ )
}
/**
@@ -293,8 +275,12 @@ object KotlinUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun isSafetyLabelChangeNotificationsEnabled(context: Context): Boolean {
- return SdkLevel.isAtLeastU() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, true) &&
+ return SdkLevel.isAtLeastU() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED,
+ true
+ ) &&
!DeviceUtils.isAuto(context) &&
!DeviceUtils.isTelevision(context) &&
!DeviceUtils.isWear(context)
@@ -306,8 +292,12 @@ object KotlinUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun safetyLabelChangesJobServiceKillSwitch(): Boolean {
- return SdkLevel.isAtLeastU() && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_SAFETY_LABEL_CHANGES_JOB_SERVICE_KILL_SWITCH, false)
+ return SdkLevel.isAtLeastU() &&
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_SAFETY_LABEL_CHANGES_JOB_SERVICE_KILL_SWITCH,
+ false
+ )
}
/** How often the safety label changes job will run. */
@@ -316,7 +306,8 @@ object KotlinUtils {
return DeviceConfig.getLong(
DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_SAFETY_LABEL_CHANGES_JOB_INTERVAL_MILLIS,
- Duration.ofDays(30).toMillis())
+ Duration.ofDays(30).toMillis()
+ )
}
/** Whether the safety label changes job should only be run when the device is idle. */
@@ -325,19 +316,24 @@ object KotlinUtils {
return DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_PRIVACY,
PROPERTY_SAFETY_LABEL_CHANGES_JOB_RUN_WHEN_IDLE,
- true)
+ true
+ )
+ }
+
+ fun isNewGrantDialogBackendEnabled(): Boolean {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_NEW_GRANT_DIALOG_BACKEND, true)
}
/**
- * Given a Map, and a List, determines which elements are in the list, but not the map, and
- * vice versa. Used primarily for determining which liveDatas are already being watched, and
- * which need to be removed or added
+ * Given a Map, and a List, determines which elements are in the list, but not the map, and vice
+ * versa. Used primarily for determining which liveDatas are already being watched, and which
+ * need to be removed or added
*
* @param oldValues A map of key type K, with any value type
* @param newValues A list of type K
- *
* @return A pair, where the first value is all items in the list, but not the map, and the
- * second is all keys in the map, but not the list
+ * second is all keys in the map, but not the list
*/
fun <K> getMapAndListDifferences(
newValues: Collection<K>,
@@ -359,7 +355,7 @@ object KotlinUtils {
*
* @param compare The function comparing two preferences, which will be used to sort
* @param hasHeader Whether the group contains a LargeHeaderPreference, which will be kept at
- * the top of the list
+ * the top of the list
*/
fun sortPreferenceGroup(
group: PreferenceGroup,
@@ -372,15 +368,17 @@ object KotlinUtils {
}
if (hasHeader) {
- preferences.sortWith(Comparator { lhs, rhs ->
- if (lhs is SettingsWithLargeHeader.LargeHeaderPreference) {
- -1
- } else if (rhs is SettingsWithLargeHeader.LargeHeaderPreference) {
- 1
- } else {
- compare(lhs, rhs)
+ preferences.sortWith(
+ Comparator { lhs, rhs ->
+ if (lhs is SettingsWithLargeHeader.LargeHeaderPreference) {
+ -1
+ } else if (rhs is SettingsWithLargeHeader.LargeHeaderPreference) {
+ 1
+ } else {
+ compare(lhs, rhs)
+ }
}
- })
+ )
} else {
preferences.sortWith(Comparator(compare))
}
@@ -395,17 +393,15 @@ object KotlinUtils {
*
* @param context The context from which to get the icon
* @param groupName The name of the permission group whose icon we want
- *
* @return The permission group's icon, the ic_perm_device_info icon if the group has no icon,
- * or the group does not exist
+ * or the group does not exist
*/
@JvmOverloads
fun getPermGroupIcon(context: Context, groupName: String, tint: Int? = null): Drawable? {
val groupInfo = Utils.getGroupInfo(groupName, context)
var icon: Drawable? = null
if (groupInfo != null && groupInfo.icon != 0) {
- icon = Utils.loadDrawable(context.packageManager, groupInfo.packageName,
- groupInfo.icon)
+ icon = Utils.loadDrawable(context.packageManager, groupInfo.packageName, groupInfo.icon)
}
if (icon == null) {
@@ -425,13 +421,15 @@ object KotlinUtils {
*
* @param context The context from which to get the label
* @param groupName The name of the permission group whose label we want
- *
* @return The permission group's label, or the group name, if the group is invalid
*/
fun getPermGroupLabel(context: Context, groupName: String): CharSequence {
val groupInfo = Utils.getGroupInfo(groupName, context) ?: return groupName
- return groupInfo.loadSafeLabel(context.packageManager, 0f,
- TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM)
+ return groupInfo.loadSafeLabel(
+ context.packageManager,
+ 0f,
+ TextUtils.SAFE_STRING_FLAG_FIRST_LINE or TextUtils.SAFE_STRING_FLAG_TRIM
+ )
}
/**
@@ -439,9 +437,8 @@ object KotlinUtils {
*
* @param context The context from which to get the description
* @param groupName The name of the permission group whose description we want
- *
* @return The permission group's description, or an empty string, if the group is invalid, or
- * its description does not exist
+ * its description does not exist
*/
fun getPermGroupDescription(context: Context, groupName: String): CharSequence {
val groupInfo = Utils.getGroupInfo(groupName, context)
@@ -457,15 +454,20 @@ object KotlinUtils {
/**
* Gets a permission's label from the system.
+ *
* @param context The context from which to get the label
* @param permName The name of the permission whose label we want
- *
* @return The permission's label, or the permission name, if the permission is invalid
*/
fun getPermInfoLabel(context: Context, permName: String): CharSequence {
return try {
- context.packageManager.getPermissionInfo(permName, 0).loadSafeLabel(
- context.packageManager, 20000.toFloat(), TextUtils.SAFE_STRING_FLAG_TRIM)
+ context.packageManager
+ .getPermissionInfo(permName, 0)
+ .loadSafeLabel(
+ context.packageManager,
+ 20000.toFloat(),
+ TextUtils.SAFE_STRING_FLAG_TRIM
+ )
} catch (e: PackageManager.NameNotFoundException) {
permName
}
@@ -473,19 +475,23 @@ object KotlinUtils {
/**
* Gets a permission's icon from the system.
+ *
* @param context The context from which to get the icon
* @param permName The name of the permission whose icon we want
- *
- * @return The permission's icon, or the permission's group icon if the icon isn't set, or
- * the ic_perm_device_info icon if the permission is invalid.
+ * @return The permission's icon, or the permission's group icon if the icon isn't set, or the
+ * ic_perm_device_info icon if the permission is invalid.
*/
fun getPermInfoIcon(context: Context, permName: String): Drawable? {
return try {
val permInfo = context.packageManager.getPermissionInfo(permName, 0)
var icon: Drawable? = null
if (permInfo.icon != 0) {
- icon = Utils.applyTint(context, permInfo.loadUnbadgedIcon(context.packageManager),
- android.R.attr.colorControlNormal)
+ icon =
+ Utils.applyTint(
+ context,
+ permInfo.loadUnbadgedIcon(context.packageManager),
+ android.R.attr.colorControlNormal
+ )
}
if (icon == null) {
@@ -495,8 +501,11 @@ object KotlinUtils {
icon
} catch (e: PackageManager.NameNotFoundException) {
- Utils.applyTint(context, context.getDrawable(R.drawable.ic_perm_device_info),
- android.R.attr.colorControlNormal)
+ Utils.applyTint(
+ context,
+ context.getDrawable(R.drawable.ic_perm_device_info),
+ android.R.attr.colorControlNormal
+ )
}
}
@@ -505,9 +514,8 @@ object KotlinUtils {
*
* @param context The context from which to get the description
* @param permName The name of the permission whose description we want
- *
- * @return The permission's description, or an empty string, if the group is invalid, or
- * its description does not exist
+ * @return The permission's description, or an empty string, if the group is invalid, or its
+ * description does not exist
*/
fun getPermInfoDescription(context: Context, permName: String): CharSequence {
return try {
@@ -519,19 +527,33 @@ object KotlinUtils {
}
/**
+ * Get the settings icon
+ *
+ * @param app The current application
+ * @param user The user for whom we want the icon
+ * @param pm The PackageManager
+ *
+ * @return Bitmap of the setting's icon, or null
+ */
+ fun getSettingsIcon(
+ app: Application,
+ user: UserHandle,
+ pm: PackageManager
+ ): Bitmap? {
+ val settingsPackageName = getPackageNameForIntent(pm,
+ Settings.ACTION_SETTINGS) ?: Constants.SETTINGS_PACKAGE_NAME_FALLBACK
+ return getBadgedPackageIconBitmap(app, user, settingsPackageName)
+ }
+
+ /**
* Gets a package's badged icon from the system.
*
* @param app The current application
* @param packageName The name of the package whose icon we want
* @param user The user for whom we want the package icon
- *
* @return The package's icon, or null, if the package does not exist
*/
- fun getBadgedPackageIcon(
- app: Application,
- packageName: String,
- user: UserHandle
- ): Drawable? {
+ fun getBadgedPackageIcon(app: Application, packageName: String, user: UserHandle): Drawable? {
return try {
val userContext = Utils.getUserContext(app, user)
val appInfo = userContext.packageManager.getApplicationInfo(packageName, 0)
@@ -542,12 +564,38 @@ object KotlinUtils {
}
/**
+ * Get the icon of a package
+ *
+ * @param application The current application
+ * @param user The user for whom we want the icon
+ * @param packageName The name of the package whose icon we want
+ *
+ * @return Bitmap of the package icon, or null
+ */
+ fun getBadgedPackageIconBitmap(
+ application: Application,
+ user: UserHandle,
+ packageName: String
+ ): Bitmap? {
+ val drawable = getBadgedPackageIcon(
+ application,
+ packageName,
+ user)
+
+ val icon = if (drawable != null) {
+ convertToBitmap(drawable)
+ } else {
+ null
+ }
+ return icon
+ }
+
+ /**
* Gets a package's badged label from the system.
*
* @param app The current application
* @param packageName The name of the package whose label we want
* @param user The user for whom we want the package label
- *
* @return The package's label
*/
fun getPackageLabel(app: Application, packageName: String, user: UserHandle): String {
@@ -561,8 +609,12 @@ object KotlinUtils {
}
fun convertToBitmap(pkgIcon: Drawable): Bitmap {
- val pkgIconBmp = Bitmap.createBitmap(pkgIcon.intrinsicWidth, pkgIcon.intrinsicHeight,
- Bitmap.Config.ARGB_8888)
+ 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)
@@ -571,19 +623,32 @@ object KotlinUtils {
}
/**
+ * Returns the name of the package that resolves the specified intent action
+ *
+ * @param pm The PackageManager
+ * @param intentAction The name of the intent action
+ *
+ * @return The package's name, or null
+ */
+ fun getPackageNameForIntent(pm: PackageManager, intentAction: String): String? {
+ val intent = Intent(intentAction)
+ return intent.resolveActivity(pm)?.packageName
+ }
+
+ /**
* 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).
*
* @param app The current application
* @param packageName The name of the package whose uid we want
* @param user The user we want the package uid for
- *
* @return The package's UID, or null if the package or user is invalid
*/
fun getPackageUid(app: Application, packageName: String, user: UserHandle): Int? {
val liveData = LightPackageInfoLiveData[packageName, user]
val liveDataUid = liveData.value?.uid
- return if (liveDataUid != null && liveData.hasActiveObservers()) liveDataUid else {
+ return if (liveDataUid != null && liveData.hasActiveObservers()) liveDataUid
+ else {
val userContext = Utils.getUserContext(app, user)
try {
val appInfo = userContext.packageManager.getApplicationInfo(packageName, 0)
@@ -594,9 +659,7 @@ object KotlinUtils {
}
}
- /**
- * Return a specific MIME type, if a set of permissions is associated with one
- */
+ /** Return a specific MIME type, if a set of permissions is associated with one */
fun getMimeTypeForPermissions(permissions: List<String>): String? {
if (permissions.contains(READ_MEDIA_IMAGES) && !permissions.contains(READ_MEDIA_VIDEO)) {
return "image/*"
@@ -614,33 +677,37 @@ object KotlinUtils {
* @param app The currenct application
* @param packageName The package name to check
* @param user The user whose package we want to check
- *
* @return true if the package is R+ (and not a work profile) or has auto revoke enabled
*/
fun isROrAutoRevokeEnabled(app: Application, packageName: String, user: UserHandle): Boolean {
val userContext = Utils.getUserContext(app, user)
val liveDataValue = LightPackageInfoLiveData[packageName, user].value
- val (targetSdk, uid) = if (liveDataValue != null) {
- liveDataValue.targetSdkVersion to liveDataValue.uid
- } else {
- val appInfo = userContext.packageManager.getApplicationInfo(packageName, 0)
- appInfo.targetSdkVersion to appInfo.uid
- }
+ val (targetSdk, uid) =
+ if (liveDataValue != null) {
+ liveDataValue.targetSdkVersion to liveDataValue.uid
+ } else {
+ val appInfo = userContext.packageManager.getApplicationInfo(packageName, 0)
+ appInfo.targetSdkVersion to appInfo.uid
+ }
if (targetSdk <= Build.VERSION_CODES.Q) {
val opsManager = app.getSystemService(AppOpsManager::class.java)!!
- return opsManager.unsafeCheckOpNoThrow(OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, uid,
- packageName) == MODE_ALLOWED
+ return opsManager.unsafeCheckOpNoThrow(
+ OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
+ uid,
+ packageName
+ ) == MODE_ALLOWED
}
return true
}
/**
- * Determine if the given permission should be treated as split from a
- * non-runtime permission for an application targeting the given SDK level.
+ * Determine if the given permission should be treated as split from a non-runtime permission
+ * for an application targeting the given SDK level.
*/
- private fun isPermissionSplitFromNonRuntime(
- app: Application,
+ @JvmStatic
+ fun isPermissionSplitFromNonRuntime(
+ app: Context,
permName: String,
targetSdk: Int
): Boolean {
@@ -664,8 +731,7 @@ object KotlinUtils {
* @param group: The LightAppPermGroup whose permission flags we wish to set
* @param flags: Pairs of <FlagInt, ShouldSetFlag>
* @param filterPermissions: A list of permissions to filter by. Only the filtered permissions
- * will be set
- *
+ * will be set
* @return A new LightAppPermGroup with the flags set.
*/
fun setGroupFlags(
@@ -690,14 +756,29 @@ object KotlinUtils {
}
// Check if flags need to be updated
if (flagMask and (perm.flags xor flagsToSet) != 0) {
- app.packageManager.updatePermissionFlags(permName, group.packageName,
- group.userHandle, *flags)
+ app.packageManager.updatePermissionFlags(
+ permName,
+ group.packageName,
+ group.userHandle,
+ *flags
+ )
}
- newPerms[permName] = LightPermission(group.packageInfo, perm.permInfo,
- perm.isGrantedIncludingAppOp, perm.flags or flagsToSet, perm.foregroundPerms)
+ newPerms[permName] =
+ LightPermission(
+ group.packageInfo,
+ perm.permInfo,
+ perm.isGrantedIncludingAppOp,
+ perm.flags or flagsToSet,
+ perm.foregroundPerms
+ )
}
- return LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ return LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant
+ )
}
/**
@@ -708,22 +789,27 @@ object KotlinUtils {
* @param app The current application
* @param group The group whose permissions should be granted
* @param filterPermissions If not specified, all permissions of the group will be granted.
- * Otherwise only permissions in {@code filterPermissions} will be
- * granted.
- *
+ * Otherwise only permissions in {@code filterPermissions} will be granted.
* @return a new LightAppPermGroup, reflecting the new state
*/
@JvmOverloads
fun grantForegroundRuntimePermissions(
app: Application,
group: LightAppPermGroup,
- filterPermissions: List<String> = group.permissions.keys.toList(),
+ filterPermissions: Collection<String> = group.permissions.keys,
isOneTime: Boolean = false,
userFixed: Boolean = false,
withoutAppOps: Boolean = false,
): LightAppPermGroup {
- return grantRuntimePermissions(app, group, false, isOneTime, userFixed,
- withoutAppOps, filterPermissions)
+ return grantRuntimePermissions(
+ app,
+ group,
+ false,
+ isOneTime,
+ userFixed,
+ withoutAppOps,
+ filterPermissions
+ )
}
/**
@@ -734,19 +820,17 @@ object KotlinUtils {
* @param app The current application
* @param group The group whose permissions should be granted
* @param filterPermissions If not specified, all permissions of the group will be granted.
- * Otherwise only permissions in {@code filterPermissions} will be
- * granted.
- *
+ * Otherwise only permissions in {@code filterPermissions} will be granted.
* @return a new LightAppPermGroup, reflecting the new state
*/
@JvmOverloads
fun grantBackgroundRuntimePermissions(
app: Application,
group: LightAppPermGroup,
- filterPermissions: List<String> = group.permissions.keys.toList()
+ filterPermissions: Collection<String> = group.permissions.keys
): LightAppPermGroup {
- return grantRuntimePermissions(app, group, true, false, false, false,
- filterPermissions)
+ return grantRuntimePermissions(app, group, grantBackground = true, isOneTime = false,
+ userFixed = false, withoutAppOps = false, filterPermissions = filterPermissions)
}
private fun grantRuntimePermissions(
@@ -756,7 +840,7 @@ object KotlinUtils {
isOneTime: Boolean = false,
userFixed: Boolean = false,
withoutAppOps: Boolean = false,
- filterPermissions: List<String> = group.permissions.keys.toList(),
+ filterPermissions: Collection<String> = group.permissions.keys
): LightAppPermGroup {
val newPerms = group.permissions.toMutableMap()
var shouldKillForAnyPermission = false
@@ -764,8 +848,8 @@ object KotlinUtils {
val perm = group.permissions[permName] ?: continue
val isBackgroundPerm = permName in group.backgroundPermNames
if (isBackgroundPerm == grantBackground) {
- val (newPerm, shouldKill) = grantRuntimePermission(app, perm, group, isOneTime,
- userFixed, withoutAppOps)
+ val (newPerm, shouldKill) =
+ grantRuntimePermission(app, perm, group, isOneTime, userFixed, withoutAppOps)
newPerms[newPerm.name] = newPerm
shouldKillForAnyPermission = shouldKillForAnyPermission || shouldKill
}
@@ -776,32 +860,48 @@ object KotlinUtils {
var permFlags = groupPerm.flags
permFlags = permFlags.clearFlag(FLAG_PERMISSION_AUTO_REVOKED)
if (groupPerm.flags != permFlags) {
- app.packageManager.updatePermissionFlags(groupPerm.name,
- group.packageInfo.packageName, PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
- permFlags, user)
+ app.packageManager.updatePermissionFlags(
+ groupPerm.name,
+ group.packageInfo.packageName,
+ PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
+ permFlags,
+ user
+ )
}
}
}
if (shouldKillForAnyPermission) {
(app.getSystemService(ActivityManager::class.java) as ActivityManager).killUid(
- group.packageInfo.uid, KILL_REASON_APP_OP_CHANGE)
+ group.packageInfo.uid,
+ KILL_REASON_APP_OP_CHANGE
+ )
}
- val newGroup = LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ val newGroup =
+ LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant
+ )
// If any permission in the group is one time granted, start one time permission session.
if (newGroup.permissions.any { it.value.isOneTime && it.value.isGrantedIncludingAppOp }) {
if (SdkLevel.isAtLeastT()) {
app.getSystemService(PermissionManager::class.java)!!.startOneTimePermissionSession(
- group.packageName, Utils.getOneTimePermissionsTimeout(),
- Utils.getOneTimePermissionsKilledDelay(false),
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE)
+ group.packageName,
+ Utils.getOneTimePermissionsTimeout(),
+ Utils.getOneTimePermissionsKilledDelay(false),
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE
+ )
} else {
app.getSystemService(PermissionManager::class.java)!!.startOneTimePermissionSession(
- group.packageName, Utils.getOneTimePermissionsTimeout(),
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
- ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE)
+ group.packageName,
+ Utils.getOneTimePermissionsTimeout(),
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_RESET_TIMER,
+ ONE_TIME_PACKAGE_IMPORTANCE_LEVEL_TO_KEEP_SESSION_ALIVE
+ )
}
}
return newGroup
@@ -813,14 +913,13 @@ object KotlinUtils {
* @param app The current application
* @param perm The permission which should be granted.
* @param group An app permission group in which to look for background or foreground
- * @param isOneTime Whether this is a one-time permission grant
- * permissions
+ * @param isOneTime Whether this is a one-time permission grant permissions
* @param userFixed Whether to mark the permissions as user fixed when granted
* @param withoutAppOps If these permission have app ops associated, and this value is true,
- * then do not grant the app op when the permission is granted, and add the REVOKED_COMPAT flag.
- *
+ * then do not grant the app op when the permission is granted, and add the REVOKED_COMPAT
+ * flag.
* @return a LightPermission and boolean pair <permission with updated state (or the original
- * state, if it wasn't changed), should kill app>
+ * state, if it wasn't changed), should kill app>
*/
private fun grantRuntimePermission(
app: Application,
@@ -833,8 +932,9 @@ object KotlinUtils {
val pkgInfo = group.packageInfo
val user = UserHandle.getUserHandleForUid(pkgInfo.uid)
val supportsRuntime = pkgInfo.targetSdkVersion >= Build.VERSION_CODES.M
- val isGrantingAllowed = (!pkgInfo.isInstantApp || perm.isInstantPerm) &&
- (supportsRuntime || !perm.isRuntimeOnly)
+ val isGrantingAllowed =
+ (!pkgInfo.isInstantApp || perm.isInstantPerm) &&
+ (supportsRuntime || !perm.isRuntimeOnly)
// Do not touch permissions fixed by the system, or permissions that cannot be granted
if (!isGrantingAllowed || perm.isSystemFixed) {
return perm to false
@@ -855,8 +955,13 @@ object KotlinUtils {
// flag, so that the PermissionPolicyService doesn't reset the app op state
if (affectsAppOp && withoutAppOps) {
oldFlags = oldFlags.setFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
- app.packageManager.updatePermissionFlags(perm.name, group.packageName,
- PERMISSION_CONTROLLER_CHANGED_FLAG_MASK, oldFlags, user)
+ app.packageManager.updatePermissionFlags(
+ perm.name,
+ group.packageName,
+ PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
+ oldFlags,
+ user
+ )
disallowAppOp(app, perm, group)
}
app.packageManager.grantRuntimePermission(group.packageName, perm.name, user)
@@ -869,11 +974,12 @@ object KotlinUtils {
shouldKill = true
isGranted = true
}
- newFlags = if (affectsAppOp && withoutAppOps) {
- newFlags.setFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
- } else {
- newFlags.clearFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
- }
+ newFlags =
+ if (affectsAppOp && withoutAppOps) {
+ newFlags.setFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
+ } else {
+ newFlags.clearFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
+ }
newFlags = newFlags.clearFlag(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)
// If this permission affects an app op, ensure the permission app op is enabled
@@ -898,11 +1004,12 @@ object KotlinUtils {
}
newFlags = newFlags.clearFlag(FLAG_PERMISSION_AUTO_REVOKED)
- newFlags = if (isOneTime) {
- newFlags.setFlag(FLAG_PERMISSION_ONE_TIME)
- } else {
- newFlags.clearFlag(FLAG_PERMISSION_ONE_TIME)
- }
+ newFlags =
+ if (isOneTime) {
+ newFlags.setFlag(FLAG_PERMISSION_ONE_TIME)
+ } else {
+ newFlags.clearFlag(FLAG_PERMISSION_ONE_TIME)
+ }
// If we newly grant background access to the fine location, double-guess the user some
// time later if this was really the right choice.
@@ -922,13 +1029,18 @@ object KotlinUtils {
}
if (oldFlags != newFlags) {
- app.packageManager.updatePermissionFlags(perm.name, group.packageInfo.packageName,
- PERMISSION_CONTROLLER_CHANGED_FLAG_MASK, newFlags, user)
+ app.packageManager.updatePermissionFlags(
+ perm.name,
+ group.packageInfo.packageName,
+ PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
+ newFlags,
+ user
+ )
}
val newState = PermState(newFlags, isGranted)
- return LightPermission(perm.pkgInfo, perm.permInfo, newState,
- perm.foregroundPerms) to shouldKill
+ return LightPermission(perm.pkgInfo, perm.permInfo, newState, perm.foregroundPerms) to
+ shouldKill
}
/**
@@ -941,9 +1053,7 @@ object KotlinUtils {
* @param userFixed If the user requested that they do not want to be asked again
* @param oneTime If the permission should be mark as one-time
* @param filterPermissions If not specified, all permissions of the group will be revoked.
- * Otherwise only permissions in {@code filterPermissions} will be
- * revoked.
- *
+ * Otherwise only permissions in {@code filterPermissions} will be revoked.
* @return a LightAppPermGroup representing the new state
*/
@JvmOverloads
@@ -953,10 +1063,17 @@ object KotlinUtils {
userFixed: Boolean = false,
oneTime: Boolean = false,
forceRemoveRevokedCompat: Boolean = false,
- filterPermissions: List<String> = group.permissions.keys.toList()
+ filterPermissions: Collection<String> = group.permissions.keys
): LightAppPermGroup {
- return revokeRuntimePermissions(app, group, false, userFixed, oneTime,
- forceRemoveRevokedCompat, filterPermissions)
+ return revokeRuntimePermissions(
+ app,
+ group,
+ false,
+ userFixed,
+ oneTime,
+ forceRemoveRevokedCompat,
+ filterPermissions
+ )
}
/**
@@ -968,9 +1085,7 @@ object KotlinUtils {
* @param group The group whose permissions should be revoked
* @param userFixed If the user requested that they do not want to be asked again
* @param filterPermissions If not specified, all permissions of the group will be revoked.
- * Otherwise only permissions in {@code filterPermissions} will be
- * revoked.
- *
+ * Otherwise only permissions in {@code filterPermissions} will be revoked.
* @return a LightAppPermGroup representing the new state
*/
@JvmOverloads
@@ -980,10 +1095,17 @@ object KotlinUtils {
userFixed: Boolean = false,
oneTime: Boolean = false,
forceRemoveRevokedCompat: Boolean = false,
- filterPermissions: List<String> = group.permissions.keys.toList()
+ filterPermissions: Collection<String> = group.permissions.keys
): LightAppPermGroup {
- return revokeRuntimePermissions(app, group, true, userFixed, oneTime,
- forceRemoveRevokedCompat, filterPermissions)
+ return revokeRuntimePermissions(
+ app,
+ group,
+ true,
+ userFixed,
+ oneTime,
+ forceRemoveRevokedCompat,
+ filterPermissions
+ )
}
private fun revokeRuntimePermissions(
@@ -993,7 +1115,7 @@ object KotlinUtils {
userFixed: Boolean,
oneTime: Boolean,
forceRemoveRevokedCompat: Boolean = false,
- filterPermissions: List<String>
+ filterPermissions: Collection<String>
): LightAppPermGroup {
val wasOneTime = group.isOneTime
val newPerms = group.permissions.toMutableMap()
@@ -1003,8 +1125,14 @@ object KotlinUtils {
val isBackgroundPerm = permName in group.backgroundPermNames
if (isBackgroundPerm == revokeBackground) {
val (newPerm, shouldKill) =
- revokeRuntimePermission(app, perm, userFixed, oneTime, forceRemoveRevokedCompat,
- group)
+ revokeRuntimePermission(
+ app,
+ perm,
+ userFixed,
+ oneTime,
+ forceRemoveRevokedCompat,
+ group
+ )
newPerms[newPerm.name] = newPerm
shouldKillForAnyPermission = shouldKillForAnyPermission || shouldKill
}
@@ -1012,15 +1140,24 @@ object KotlinUtils {
if (shouldKillForAnyPermission && !shouldSkipKillForGroup(app, group)) {
(app.getSystemService(ActivityManager::class.java) as ActivityManager).killUid(
- group.packageInfo.uid, KILL_REASON_APP_OP_CHANGE)
+ group.packageInfo.uid,
+ KILL_REASON_APP_OP_CHANGE
+ )
}
- val newGroup = LightAppPermGroup(group.packageInfo, group.permGroupInfo, newPerms,
- group.hasInstallToRuntimeSplit, group.specialLocationGrant)
+ val newGroup =
+ LightAppPermGroup(
+ group.packageInfo,
+ group.permGroupInfo,
+ newPerms,
+ group.hasInstallToRuntimeSplit,
+ group.specialLocationGrant
+ )
if (wasOneTime && !anyPermsOfPackageOneTimeGranted(app, newGroup.packageInfo, newGroup)) {
app.getSystemService(PermissionManager::class.java)!!.stopOneTimePermissionSession(
- group.packageName)
+ group.packageName
+ )
}
return newGroup
}
@@ -1042,8 +1179,9 @@ object KotlinUtils {
postRevokeHandler: Runnable?
) {
GlobalScope.launch(Dispatchers.Main) {
- val group = LightAppPermGroupLiveData[packageName, permissionGroupName, user]
- .getInitializedValue()
+ val group =
+ LightAppPermGroupLiveData[packageName, permissionGroupName, user]
+ .getInitializedValue()
if (group != null) {
revokeBackgroundRuntimePermissions(context.application, group)
}
@@ -1059,7 +1197,6 @@ object KotlinUtils {
* @param app The current application
* @param packageInfo The packageInfo we wish to examine
* @param group Optional, the current app permission group we are examining
- *
* @return true if any permission in the package is granted for one time, false otherwise
*/
private fun anyPermsOfPackageOneTimeGranted(
@@ -1075,11 +1212,12 @@ object KotlinUtils {
if (permName in group?.permissions ?: emptyMap()) {
continue
}
- val flags = app.packageManager.getPermissionFlags(permName, packageInfo.packageName,
- user) and FLAG_PERMISSION_ONE_TIME
- val granted = packageInfo.requestedPermissionsFlags[idx] ==
- PackageManager.PERMISSION_GRANTED &&
- (flags and FLAG_PERMISSION_REVOKED_COMPAT) == 0
+ val flags =
+ app.packageManager.getPermissionFlags(permName, packageInfo.packageName, user) and
+ FLAG_PERMISSION_ONE_TIME
+ val granted =
+ packageInfo.requestedPermissionsFlags[idx] == PackageManager.PERMISSION_GRANTED &&
+ (flags and FLAG_PERMISSION_REVOKED_COMPAT) == 0
if (granted && (flags and FLAG_PERMISSION_ONE_TIME) != 0) {
return true
}
@@ -1093,10 +1231,9 @@ object KotlinUtils {
* @param perm The permission which should be revoked.
* @param userFixed If the user requested that they do not want to be asked again
* @param group An optional app permission group in which to look for background or foreground
- * permissions
- *
+ * permissions
* @return a LightPermission and boolean pair <permission with updated state (or the original
- * state, if it wasn't changed), should kill app>
+ * state, if it wasn't changed), should kill app>
*/
private fun revokeRuntimePermission(
app: Application,
@@ -1120,11 +1257,20 @@ object KotlinUtils {
val affectsAppOp = permissionToOp(perm.name) != null || perm.isBackgroundPermission
if (perm.isGrantedIncludingAppOp || (perm.isCompatRevoked && forceRemoveRevokedCompat)) {
- if (supportsRuntime && !isPermissionSplitFromNonRuntime(app, perm.name,
- group.packageInfo.targetSdkVersion)) {
+ if (
+ supportsRuntime &&
+ !isPermissionSplitFromNonRuntime(
+ app,
+ perm.name,
+ group.packageInfo.targetSdkVersion
+ )
+ ) {
// Revoke the permission if needed.
- app.packageManager.revokeRuntimePermission(group.packageInfo.packageName,
- perm.name, user)
+ app.packageManager.revokeRuntimePermission(
+ group.packageInfo.packageName,
+ perm.name,
+ user
+ )
isGranted = false
if (forceRemoveRevokedCompat) {
newFlags = newFlags.clearFlag(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)
@@ -1149,18 +1295,26 @@ object KotlinUtils {
// Update the permission flags.
// Take a note that the user fixed the permission, if applicable.
- newFlags = if (userFixed) newFlags.setFlag(PackageManager.FLAG_PERMISSION_USER_FIXED)
- else newFlags.clearFlag(PackageManager.FLAG_PERMISSION_USER_FIXED)
- newFlags = if (oneTime) newFlags.clearFlag(PackageManager.FLAG_PERMISSION_USER_SET)
- else newFlags.setFlag(PackageManager.FLAG_PERMISSION_USER_SET)
- newFlags = if (oneTime) newFlags.setFlag(PackageManager.FLAG_PERMISSION_ONE_TIME)
- else newFlags.clearFlag(PackageManager.FLAG_PERMISSION_ONE_TIME)
+ newFlags =
+ if (userFixed) newFlags.setFlag(PackageManager.FLAG_PERMISSION_USER_FIXED)
+ else newFlags.clearFlag(PackageManager.FLAG_PERMISSION_USER_FIXED)
+ newFlags =
+ if (oneTime) newFlags.clearFlag(PackageManager.FLAG_PERMISSION_USER_SET)
+ else newFlags.setFlag(PackageManager.FLAG_PERMISSION_USER_SET)
+ newFlags =
+ if (oneTime) newFlags.setFlag(PackageManager.FLAG_PERMISSION_ONE_TIME)
+ else newFlags.clearFlag(PackageManager.FLAG_PERMISSION_ONE_TIME)
newFlags = newFlags.clearFlag(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)
newFlags = newFlags.clearFlag(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED)
if (perm.flags != newFlags) {
- app.packageManager.updatePermissionFlags(perm.name, group.packageInfo.packageName,
- PERMISSION_CONTROLLER_CHANGED_FLAG_MASK, newFlags, user)
+ app.packageManager.updatePermissionFlags(
+ perm.name,
+ group.packageInfo.packageName,
+ PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
+ newFlags,
+ user
+ )
}
// If we revoke background access to the fine location, we trigger a check to remove
@@ -1176,17 +1330,18 @@ object KotlinUtils {
}
if (cancelLocationAccessWarning) {
// cancel location access warning notification
- LocationAccessCheck(app, null).cancelBackgroundAccessWarningNotification(
- group.packageInfo.packageName,
- user,
- true
- )
+ LocationAccessCheck(app, null)
+ .cancelBackgroundAccessWarningNotification(
+ group.packageInfo.packageName,
+ user,
+ true
+ )
}
}
val newState = PermState(newFlags, isGranted)
- return LightPermission(perm.pkgInfo, perm.permInfo, newState,
- perm.foregroundPerms) to shouldKill
+ return LightPermission(perm.pkgInfo, perm.permInfo, newState, perm.foregroundPerms) to
+ shouldKill
}
private fun Int.setFlag(flagToSet: Int): Int {
@@ -1200,27 +1355,20 @@ object KotlinUtils {
/**
* Allow the app op for a permission/uid.
*
- * <p>There are three cases:
- * <dl>
- * <dt>The permission is not split into foreground/background</dt>
- * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd>
- * <dt>The permission is a foreground permission:</dt>
- * <dd><dl><dt>The background permission permission is granted</dt>
- * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd>
- * <dt>The background permission permission is <u>not</u> granted</dt>
- * <dd>The app op matching the permission will be set to
- * {@link AppOpsManager#MODE_FOREGROUND}</dd>
- * </dl></dd>
- * <dt>The permission is a background permission:</dt>
- * <dd>All granted foreground permissions for this background permission will be set to
- * {@link AppOpsManager#MODE_ALLOWED}</dd>
- * </dl>
+ * <p>There are three cases: <dl> <dt>The permission is not split into
+ * foreground/background</dt> <dd>The app op matching the permission will be set to {@link
+ * AppOpsManager#MODE_ALLOWED}</dd> <dt>The permission is a foreground permission:</dt>
+ * <dd><dl><dt>The background permission permission is granted</dt> <dd>The app op matching the
+ * permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd> <dt>The background
+ * permission permission is <u>not</u> granted</dt> <dd>The app op matching the permission will
+ * be set to {@link AppOpsManager#MODE_FOREGROUND}</dd> </dl></dd> <dt>The permission is a
+ * background permission:</dt> <dd>All granted foreground permissions for this background
+ * permission will be set to {@link AppOpsManager#MODE_ALLOWED}</dd> </dl>
*
* @param app The current application
* @param perm The LightPermission whose app op should be allowed
- * @param group The LightAppPermGroup which will be looked in for foreground or
- * background LightPermission objects
- *
+ * @param group The LightAppPermGroup which will be looked in for foreground or background
+ * LightPermission objects
* @return {@code true} iff app-op was changed
*/
private fun allowAppOp(
@@ -1239,25 +1387,29 @@ object KotlinUtils {
val appOpName = permissionToOp(foregroundPermName) ?: continue
if (fgPerm != null && fgPerm.isGrantedIncludingAppOp) {
- wasChanged = setOpMode(appOpName, uid, packageName, MODE_ALLOWED,
- appOpsManager) || wasChanged
+ wasChanged =
+ setOpMode(appOpName, uid, packageName, MODE_ALLOWED, appOpsManager) ||
+ wasChanged
}
}
} else {
val appOpName = permissionToOp(perm.name) ?: return false
if (perm.backgroundPermission != null) {
- wasChanged = if (group.permissions.containsKey(perm.backgroundPermission)) {
- val bgPerm = group.permissions[perm.backgroundPermission]
- val mode = if (bgPerm != null && bgPerm.isGrantedIncludingAppOp) MODE_ALLOWED
- else MODE_FOREGROUND
-
- setOpMode(appOpName, uid, packageName, mode, appOpsManager)
- } else {
- // The app requested a permission that has a background permission but it did
- // not request the background permission, hence it can never get background
- // access
- setOpMode(appOpName, uid, packageName, MODE_FOREGROUND, appOpsManager)
- }
+ wasChanged =
+ if (group.permissions.containsKey(perm.backgroundPermission)) {
+ val bgPerm = group.permissions[perm.backgroundPermission]
+ val mode =
+ if (bgPerm != null && bgPerm.isGrantedIncludingAppOp) MODE_ALLOWED
+ else MODE_FOREGROUND
+
+ setOpMode(appOpName, uid, packageName, mode, appOpsManager)
+ } else {
+ // The app requested a permission that has a background permission but it
+ // did
+ // not request the background permission, hence it can never get background
+ // access
+ setOpMode(appOpName, uid, packageName, MODE_FOREGROUND, appOpsManager)
+ }
} else {
wasChanged = setOpMode(appOpName, uid, packageName, MODE_ALLOWED, appOpsManager)
}
@@ -1268,22 +1420,17 @@ object KotlinUtils {
/**
* Disallow the app op for a permission/uid.
*
- * <p>There are three cases:
- * <dl>
- * <dt>The permission is not split into foreground/background</dt>
- * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_IGNORED}</dd>
- * <dt>The permission is a foreground permission:</dt>
- * <dd>The app op matching the permission will be set to {@link AppOpsManager#MODE_IGNORED}</dd>
- * <dt>The permission is a background permission:</dt>
- * <dd>All granted foreground permissions for this background permission will be set to
- * {@link AppOpsManager#MODE_FOREGROUND}</dd>
- * </dl>
+ * <p>There are three cases: <dl> <dt>The permission is not split into
+ * foreground/background</dt> <dd>The app op matching the permission will be set to {@link
+ * AppOpsManager#MODE_IGNORED}</dd> <dt>The permission is a foreground permission:</dt> <dd>The
+ * app op matching the permission will be set to {@link AppOpsManager#MODE_IGNORED}</dd> <dt>The
+ * permission is a background permission:</dt> <dd>All granted foreground permissions for this
+ * background permission will be set to {@link AppOpsManager#MODE_FOREGROUND}</dd> </dl>
*
* @param app The current application
* @param perm The LightPermission whose app op should be allowed
- * @param group The LightAppPermGroup which will be looked in for foreground or
- * background LightPermission objects
- *
+ * @param group The LightAppPermGroup which will be looked in for foreground or background
+ * LightPermission objects
* @return {@code true} iff app-op was changed
*/
private fun disallowAppOp(
@@ -1301,8 +1448,9 @@ object KotlinUtils {
val fgPerm = group.permissions[foregroundPermName]
if (fgPerm != null && fgPerm.isGrantedIncludingAppOp) {
val appOpName = permissionToOp(foregroundPermName) ?: return false
- wasChanged = wasChanged || setOpMode(appOpName, uid, packageName,
- MODE_FOREGROUND, appOpsManager)
+ wasChanged =
+ wasChanged ||
+ setOpMode(appOpName, uid, packageName, MODE_FOREGROUND, appOpsManager)
}
}
} else {
@@ -1320,7 +1468,6 @@ object KotlinUtils {
* @param packageName The package the app-op belongs to
* @param mode The new mode
* @param manager The app ops manager to use to change the app op
- *
* @return {@code true} iff app-op was changed
*/
private fun setOpMode(
@@ -1343,22 +1490,25 @@ object KotlinUtils {
return false
}
- return shouldSkipKillOnPermDeny(app, POST_NOTIFICATIONS, group.packageName,
- group.userHandle)
+ return shouldSkipKillOnPermDeny(
+ app,
+ POST_NOTIFICATIONS,
+ group.packageName,
+ group.userHandle
+ )
}
/**
* Determine if the usual "kill app on permission denial" should be skipped. It should be
- * skipped if the permission is POST_NOTIFICATIONS, the app holds the BACKUP permission, and
- * a backup restore is currently in progress.
+ * skipped if the permission is POST_NOTIFICATIONS, the app holds the BACKUP permission, and a
+ * backup restore is currently in progress.
*
* @param app the current application
* @param permission the permission being denied
* @param packageName the package the permission was denied for
* @param user the user whose package the permission was denied for
- *
* @return true if the permission denied was POST_NOTIFICATIONS, the app is a backup app, and a
- * backup restore is in progress, false otherwise
+ * backup restore is in progress, false otherwise
*/
fun shouldSkipKillOnPermDeny(
app: Application,
@@ -1367,17 +1517,27 @@ object KotlinUtils {
user: UserHandle
): Boolean {
val userContext: Context = Utils.getUserContext(app, user)
- if (permission != POST_NOTIFICATIONS || userContext.packageManager
- .checkPermission(BACKUP, packageName) != PackageManager.PERMISSION_GRANTED) {
+ if (
+ permission != POST_NOTIFICATIONS ||
+ userContext.packageManager.checkPermission(BACKUP, packageName) !=
+ PackageManager.PERMISSION_GRANTED
+ ) {
return false
}
return try {
- val isInSetup = Settings.Secure.getInt(userContext.contentResolver,
- Settings.Secure.USER_SETUP_COMPLETE, user.identifier) == 0
- val isInDeferredSetup = Settings.Secure.getInt(userContext.contentResolver,
- Settings.Secure.USER_SETUP_PERSONALIZATION_STATE, user.identifier) ==
- Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED
+ val isInSetup =
+ Settings.Secure.getInt(
+ userContext.contentResolver,
+ Settings.Secure.USER_SETUP_COMPLETE,
+ user.identifier
+ ) == 0
+ val isInDeferredSetup =
+ Settings.Secure.getInt(
+ userContext.contentResolver,
+ Settings.Secure.USER_SETUP_PERSONALIZATION_STATE,
+ user.identifier
+ ) == Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED
isInSetup || isInDeferredSetup
} catch (e: Settings.SettingNotFoundException) {
Log.w(LOG_TAG, "Failed to check if the user is in restore: $e")
@@ -1391,22 +1551,27 @@ object KotlinUtils {
*
* @param context: The context from which to retrieve the package
* @param packageName: The package name to check
- *
* @return whether or not the given package has a launch intent
*/
fun packageHasLaunchIntent(context: Context, packageName: String): Boolean {
val intentToResolve = Intent(ACTION_MAIN)
intentToResolve.addCategory(CATEGORY_INFO)
intentToResolve.setPackage(packageName)
- var resolveInfos = context.packageManager.queryIntentActivities(intentToResolve,
- MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)
+ var resolveInfos =
+ context.packageManager.queryIntentActivities(
+ intentToResolve,
+ MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE
+ )
if (resolveInfos.size <= 0) {
intentToResolve.removeCategory(CATEGORY_INFO)
intentToResolve.addCategory(CATEGORY_LAUNCHER)
intentToResolve.setPackage(packageName)
- resolveInfos = context.packageManager.queryIntentActivities(intentToResolve,
- MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE)
+ resolveInfos =
+ context.packageManager.queryIntentActivities(
+ intentToResolve,
+ MATCH_DIRECT_BOOT_AWARE or MATCH_DIRECT_BOOT_UNAWARE
+ )
}
return resolveInfos.size > 0
}
@@ -1424,39 +1589,55 @@ object KotlinUtils {
isFineSelected: Boolean
) {
if (isFineSelected) {
- setGroupFlags(app, group,
+ setGroupFlags(
+ app,
+ group,
PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY to true,
- filterPermissions = listOf(ACCESS_FINE_LOCATION))
- setGroupFlags(app, group,
+ filterPermissions = listOf(ACCESS_FINE_LOCATION)
+ )
+ setGroupFlags(
+ app,
+ group,
PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY to false,
- filterPermissions = listOf(Manifest.permission.ACCESS_COARSE_LOCATION))
+ filterPermissions = listOf(Manifest.permission.ACCESS_COARSE_LOCATION)
+ )
} else {
- setGroupFlags(app, group,
+ setGroupFlags(
+ app,
+ group,
PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY to false,
- filterPermissions = listOf(ACCESS_FINE_LOCATION))
- setGroupFlags(app, group,
+ filterPermissions = listOf(ACCESS_FINE_LOCATION)
+ )
+ setGroupFlags(
+ app,
+ group,
PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY to true,
- filterPermissions = listOf(Manifest.permission.ACCESS_COARSE_LOCATION))
+ filterPermissions = listOf(Manifest.permission.ACCESS_COARSE_LOCATION)
+ )
}
}
/**
- * Determines whether we should show the safety protection resources.
- * We show the resources only if
- * (1) the build version is T or after and
- * (2) the feature flag safety_protection_enabled is enabled and
- * (3) the config value config_safetyProtectionEnabled is enabled/true and
- * (4) the resources exist (currently the resources only exist on GMS devices)
+ * Determines whether we should show the safety protection resources. We show the resources only
+ * if (1) the build version is T or after and (2) the feature flag safety_protection_enabled is
+ * enabled and (3) the config value config_safetyProtectionEnabled is enabled/true and (4) the
+ * resources exist (currently the resources only exist on GMS devices)
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
fun shouldShowSafetyProtectionResources(context: Context): Boolean {
return try {
SdkLevel.isAtLeastT() &&
DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY, SAFETY_PROTECTION_RESOURCES_ENABLED, false) &&
- context.getResources().getBoolean(
- Resources.getSystem()
- .getIdentifier("config_safetyProtectionEnabled", "bool", "android")) &&
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_PROTECTION_RESOURCES_ENABLED,
+ false
+ ) &&
+ context
+ .getResources()
+ .getBoolean(
+ Resources.getSystem()
+ .getIdentifier("config_safetyProtectionEnabled", "bool", "android")
+ ) &&
context.getDrawable(android.R.drawable.ic_safety_protection) != null &&
!context.getString(android.R.string.safety_protection_display_text).isNullOrEmpty()
} catch (e: Resources.NotFoundException) {
@@ -1480,8 +1661,7 @@ object KotlinUtils {
installerPackageName: String?,
packageName: String?
): Intent? {
- val intent: Intent = Intent(Intent.ACTION_SHOW_APP_INFO)
- .setPackage(installerPackageName)
+ val intent: Intent = Intent(Intent.ACTION_SHOW_APP_INFO).setPackage(installerPackageName)
val result: Intent? = resolveActivityForIntent(context, intent)
if (result != null) {
result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName)
@@ -1512,9 +1692,10 @@ object KotlinUtils {
val color: Int
// If U resources are available, and this is a U+ device, use those
if (SdkLevel.isAtLeastU()) {
- val scContext = SafetyCenterResourcesContext(context)
- val uIcon = scContext.getIconByDrawableName("ic_notification_badge_general")
- val uColor = scContext.getColorByName("notification_tint_normal")
+ val safetyCenterResourcesApk = SafetyCenterResourcesApk(context)
+ val uIcon =
+ safetyCenterResourcesApk.getIconByDrawableName("ic_notification_badge_general")
+ val uColor = safetyCenterResourcesApk.getColorByName("notification_tint_normal")
if (uIcon != null && uColor != null) {
appLabel = context.getString(R.string.safety_privacy_qs_tile_title)
return NotificationResources(appLabel, uIcon, uColor)
@@ -1523,24 +1704,21 @@ object KotlinUtils {
// Use PbA branding if available, otherwise default to more generic branding
if (shouldShowSafetyProtectionResources(context)) {
- appLabel = Html.fromHtml(context.getString(
- android.R.string.safety_protection_display_text), 0).toString()
- smallIcon =
- Icon.createWithResource(context, android.R.drawable.ic_safety_protection)
+ appLabel =
+ Html.fromHtml(context.getString(android.R.string.safety_protection_display_text), 0)
+ .toString()
+ smallIcon = Icon.createWithResource(context, android.R.drawable.ic_safety_protection)
color = context.getColor(R.color.safety_center_info)
} else {
appLabel = context.getString(R.string.safety_center_notification_app_label)
- smallIcon =
- Icon.createWithResource(context, R.drawable.ic_settings_notification)
+ smallIcon = Icon.createWithResource(context, R.drawable.ic_settings_notification)
color = context.getColor(android.R.color.system_notification_accent_color)
}
return NotificationResources(appLabel, smallIcon, color)
}
}
-/**
- * Get the [value][LiveData.getValue], suspending until [isInitialized] if not yet so
- */
+/** Get the [value][LiveData.getValue], suspending until [isInitialized] if not yet so */
suspend fun <T, LD : LiveData<T>> LD.getInitializedValue(
observe: LD.(Observer<T>) -> Unit = { observeForever(it) },
isValueInitialized: LD.() -> Boolean = { value != null }
@@ -1557,14 +1735,13 @@ suspend fun <T, LD : LiveData<T>> LD.getInitializedValue(
observer.getAndSet(null)?.let { observerSnapshot ->
removeObserver(observerSnapshot)
continuation.resume(newValue)
+ }
}
}
}
- })
+ )
- GlobalScope.launch(Dispatchers.Main) {
- observe(observer.get())
- }
+ GlobalScope.launch(Dispatchers.Main) { observe(observer.get()) }
}
}
}
@@ -1572,8 +1749,8 @@ suspend fun <T, LD : LiveData<T>> LD.getInitializedValue(
/**
* A parallel equivalent of [map]
*
- * Starts the given suspending function for each item in the collection without waiting for
- * previous ones to complete, then suspends until all the started operations finish.
+ * Starts the given suspending function for each item in the collection without waiting for previous
+ * ones to complete, then suspends until all the started operations finish.
*/
suspend inline fun <T, R> Iterable<T>.mapInParallel(
context: CoroutineContext,
@@ -1595,8 +1772,8 @@ suspend inline fun <T> Iterable<T>.forEachInParallel(
}
/**
- * Check that we haven't already started transitioning to a given destination. If we haven't,
- * start navigating to that destination.
+ * Check that we haven't already started transitioning to a given destination. If we haven't, start
+ * navigating to that destination.
*
* @param destResId The ID of the desired destination
* @param args The optional bundle of args to be passed to the destination
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
index b06a09b28..32d3a5325 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/PermissionMapping.kt
@@ -334,6 +334,10 @@ object PermissionMapping {
* grant. Otherwise, ACCESS_MEDIA_LOCATION is considered a full grant (for compatibility).
*/
fun getPartialStorageGrantPermissionsForGroup(group: LightAppPermGroup): Set<String> {
+ if (!KotlinUtils.isPhotoPickerPromptSupported()) {
+ return emptySet()
+ }
+
val appSupportsPickerPrompt = group
.permissions[Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED]?.isImplicit == false
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
index d4354bd72..351cb2178 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/Utils.java
@@ -42,11 +42,10 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_W
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.health.connect.HealthConnectManager.ACTION_MANAGE_HEALTH_PERMISSIONS;
+import static android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP;
import static android.os.UserHandle.myUserId;
-
import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
-
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.Manifest;
@@ -73,6 +72,7 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.SensorPrivacyManager;
+import android.health.connect.HealthConnectManager;
import android.os.Binder;
import android.os.Build;
import android.os.Parcelable;
@@ -109,6 +109,8 @@ import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup;
import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo;
+import kotlin.Triple;
+
import java.lang.annotation.Retention;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
@@ -120,8 +122,6 @@ import java.util.Locale;
import java.util.Random;
import java.util.Set;
-import kotlin.Triple;
-
public final class Utils {
@Retention(SOURCE)
@@ -160,9 +160,6 @@ public final class Utils {
public static final String PROPERTY_SYSTEM_EXEMPT_HIBERNATION_ENABLED =
"system_exempt_hibernation_enabled";
- /** Whether to show the Permissions Hub. */
- private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
-
/** The timeout for one-time permissions */
private static final String PROPERTY_ONE_TIME_PERMISSIONS_TIMEOUT_MILLIS =
"one_time_permissions_timeout_millis";
@@ -195,9 +192,6 @@ public final class Utils {
public static final String PROPERTY_PERMISSION_DECISIONS_MAX_DATA_AGE_MILLIS =
"permission_decisions_max_data_age_millis";
- /** Whether or not warning banner is displayed when device sensors are off **/
- public static final String PROPERTY_WARNING_BANNER_DISPLAY_ENABLED = "warning_banner_enabled";
-
/** All permission whitelists. */
public static final int FLAGS_PERMISSION_WHITELIST_ALL =
PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
@@ -222,10 +216,13 @@ public final class Utils {
public static final long ONE_TIME_PERMISSIONS_KILLED_DELAY_MILLIS = 5 * 1000;
private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_REQUEST_DETAIL_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_RES;
+ private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES;
private static final ArrayMap<String, Integer> PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES;
/** Permission -> Sensor codes */
@@ -282,6 +279,38 @@ public final class Utils {
PERM_GROUP_REQUEST_RES.put(SENSORS, R.string.permgrouprequest_sensors);
PERM_GROUP_REQUEST_RES.put(NOTIFICATIONS, R.string.permgrouprequest_notifications);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CONTACTS,
+ R.string.permgrouprequest_device_aware_contacts);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(LOCATION,
+ R.string.permgrouprequest_device_aware_location);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(NEARBY_DEVICES,
+ R.string.permgrouprequest_device_aware_nearby_devices);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CALENDAR,
+ R.string.permgrouprequest_device_aware_calendar);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(SMS, R.string.permgrouprequest_device_aware_sms);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(STORAGE,
+ R.string.permgrouprequest_device_aware_storage);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(READ_MEDIA_AURAL,
+ R.string.permgrouprequest_device_aware_read_media_aural);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(READ_MEDIA_VISUAL,
+ R.string.permgrouprequest_device_aware_read_media_visual);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(MICROPHONE,
+ R.string.permgrouprequest_device_aware_microphone);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES
+ .put(ACTIVITY_RECOGNITION,
+ R.string.permgrouprequest_device_aware_activityRecognition);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CAMERA,
+ R.string.permgrouprequest_device_aware_camera);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(CALL_LOG,
+ R.string.permgrouprequest_device_aware_calllog);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(PHONE,
+ R.string.permgrouprequest_device_aware_phone);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(SENSORS,
+ R.string.permgrouprequest_device_aware_sensors);
+ PERM_GROUP_REQUEST_DEVICE_AWARE_RES.put(NOTIFICATIONS,
+ R.string.permgrouprequest_device_aware_notifications);
+
PERM_GROUP_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_REQUEST_DETAIL_RES.put(LOCATION, R.string.permgrouprequestdetail_location);
PERM_GROUP_REQUEST_DETAIL_RES.put(MICROPHONE, R.string.permgrouprequestdetail_microphone);
@@ -297,6 +326,16 @@ public final class Utils {
PERM_GROUP_BACKGROUND_REQUEST_RES
.put(SENSORS, R.string.permgroupbackgroundrequest_sensors);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(LOCATION, R.string.permgroupbackgroundrequest_device_aware_location);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(MICROPHONE, R.string.permgroupbackgroundrequest_device_aware_microphone);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(CAMERA, R.string.permgroupbackgroundrequest_device_aware_camera);
+ PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES
+ .put(SENSORS, R.string.permgroupbackgroundrequest_device_aware_sensors);
+
PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_BACKGROUND_REQUEST_DETAIL_RES
.put(LOCATION, R.string.permgroupbackgroundrequestdetail_location);
@@ -313,6 +352,16 @@ public final class Utils {
PERM_GROUP_UPGRADE_REQUEST_RES.put(CAMERA, R.string.permgroupupgraderequest_camera);
PERM_GROUP_UPGRADE_REQUEST_RES.put(SENSORS, R.string.permgroupupgraderequest_sensors);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES = new ArrayMap<>();
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(LOCATION,
+ R.string.permgroupupgraderequest_device_aware_location);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(MICROPHONE,
+ R.string.permgroupupgraderequest_device_aware_microphone);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(CAMERA,
+ R.string.permgroupupgraderequest_device_aware_camera);
+ PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.put(SENSORS,
+ R.string.permgroupupgraderequest_device_aware_sensors);
+
PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES = new ArrayMap<>();
PERM_GROUP_UPGRADE_REQUEST_DETAIL_RES
.put(LOCATION, R.string.permgroupupgraderequestdetail_location);
@@ -698,11 +747,16 @@ public final class Utils {
* @param groupName The name of the permission group
* @param context A context to resolve resources
* @param requestRes The resource id of the grant request message
- *
* @return The formatted message to be used as title when granting permissions
*/
- public static CharSequence getRequestMessage(CharSequence appLabel, String packageName,
- String groupName, Context context, @StringRes int requestRes) {
+ @NonNull
+ public static CharSequence getRequestMessage(
+ @NonNull String appLabel,
+ @NonNull String packageName,
+ @NonNull String groupName,
+ @NonNull Context context,
+ @StringRes int requestRes) {
+ String escapedAppLabel = Html.escapeHtml(appLabel);
boolean isIsolatedStorage;
try {
@@ -712,15 +766,76 @@ public final class Utils {
}
if (groupName.equals(STORAGE) && isIsolatedStorage) {
return Html.fromHtml(
- String.format(context.getResources().getConfiguration().getLocales().get(0),
+ String.format(
+ context.getResources().getConfiguration().getLocales().get(0),
context.getString(R.string.permgrouprequest_storage_isolated),
- appLabel), 0);
+ escapedAppLabel),
+ 0);
} else if (requestRes != 0) {
- return Html.fromHtml(context.getResources().getString(requestRes, appLabel), 0);
+ return Html.fromHtml(context.getResources().getString(requestRes, escapedAppLabel), 0);
}
- return Html.fromHtml(context.getString(R.string.permission_warning_template, appLabel,
- loadGroupDescription(context, groupName, context.getPackageManager())), 0);
+ return Html.fromHtml(
+ context.getString(
+ R.string.permission_warning_template,
+ escapedAppLabel,
+ loadGroupDescription(context, groupName, context.getPackageManager())),
+ 0);
+ }
+
+ /**
+ * Get the message shown to grant a permission group to an app.
+ *
+ * @param appLabel The label of the app
+ * @param packageName The package name of the app
+ * @param groupName The name of the permission group
+ * @param context A context to resolve resources
+ * @param requestRes The resource id of the grant request message
+ * @return The formatted message to be used as title when granting permissions
+ */
+ @NonNull
+ public static CharSequence getRequestMessage(
+ @NonNull String appLabel,
+ @NonNull String packageName,
+ @NonNull String groupName,
+ @NonNull String deviceLabel,
+ @NonNull Context context,
+ int deviceId,
+ @StringRes int requestRes) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return getRequestMessage(appLabel, packageName, groupName, context, requestRes);
+ }
+ String escapedAppLabel = Html.escapeHtml(appLabel);
+
+ boolean isIsolatedStorage;
+ try {
+ isIsolatedStorage = !isNonIsolatedStorage(context, packageName);
+ } catch (NameNotFoundException e) {
+ isIsolatedStorage = false;
+ }
+ if (groupName.equals(STORAGE) && isIsolatedStorage) {
+ String escapedDeviceLabel = Html.escapeHtml(deviceLabel);
+ return Html.fromHtml(
+ String.format(
+ context.getResources().getConfiguration().getLocales().get(0),
+ context.getString(
+ R.string.permgrouprequest_device_aware_storage_isolated),
+ escapedAppLabel,
+ escapedDeviceLabel),
+ 0);
+
+ } else if (requestRes != 0) {
+ String escapedDeviceLabel = Html.escapeHtml(deviceLabel);
+ return Html.fromHtml(context.getResources().getString(requestRes, escapedAppLabel,
+ escapedDeviceLabel), 0);
+ }
+
+ return Html.fromHtml(
+ context.getString(
+ R.string.permission_warning_template,
+ escapedAppLabel,
+ loadGroupDescription(context, groupName, context.getPackageManager())),
+ 0);
}
private static CharSequence loadGroupDescription(Context context, String groupName,
@@ -943,6 +1058,70 @@ public final class Utils {
}
/**
+ * Returns true if the group name passed is that of the Platform health group.
+ * @param permGroupName name of the group that needs to be checked.
+ */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static Boolean isHealthPermissionGroup(String permGroupName) {
+ return SdkLevel.isAtLeastU() && HEALTH_PERMISSION_GROUP.equals(permGroupName);
+ }
+
+ /**
+ * Return whether health permission setting entry should be shown or not
+ *
+ * Should not show Health permissions preference if the package doesn't handle
+ * VIEW_PERMISSION_USAGE_INTENT.
+ *
+ * Will show if above is true AND permission is already granted.
+ *
+ * @param packageInfo the {@link PackageInfo} app which uses the permission
+ * @param permGroupName the health permission group name to show
+ * @return {@code TRUE} iff health permission should be shown
+ */
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static Boolean shouldShowHealthPermission(LightPackageInfo packageInfo,
+ String permGroupName) {
+ if (!isHealthPermissionGroup(permGroupName)) {
+ return false;
+ }
+
+ PermissionControllerApplication app = PermissionControllerApplication.get();
+ PackageManager pm = app.getPackageManager();
+ Context context = getUserContext(app, UserHandle.getUserHandleForUid(packageInfo.getUid()));
+
+ List<PermissionInfo> permissions = new ArrayList<>();
+ try {
+ permissions.addAll(getPermissionInfosForGroup(pm, permGroupName));
+ } catch (NameNotFoundException e) {
+ Log.e(LOG_TAG, "No permissions found for permission group " + permGroupName);
+ return false;
+ }
+
+ // Check in permission is already granted as we should not hide it in the UX at that point.
+ List<String> grantedPermissions = packageInfo.getGrantedPermissions();
+ for (PermissionInfo permission : permissions) {
+ boolean isCurrentlyGranted = grantedPermissions.contains(permission.name);
+ if (isCurrentlyGranted) {
+ Log.d(LOG_TAG, "At least one Health permission group permission is granted, "
+ + "show permission group entry");
+ return true;
+ }
+ }
+
+ Intent viewUsageIntent = new Intent(Intent.ACTION_VIEW_PERMISSION_USAGE);
+ viewUsageIntent.addCategory(HealthConnectManager.CATEGORY_HEALTH_PERMISSIONS);
+ viewUsageIntent.setPackage(packageInfo.getPackageName());
+
+ ResolveInfo resolveInfo = pm.resolveActivity(viewUsageIntent, PackageManager.MATCH_ALL);
+ if (resolveInfo == null) {
+ Log.e(LOG_TAG, "Package that asks for Health permission must also handle "
+ + "VIEW_PERMISSION_USAGE_INTENT.");
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Get a device protected storage based shared preferences. Avoid storing sensitive data in it.
*
* @param context the context to get the shared preferences
@@ -1013,7 +1192,21 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getRequest(String groupName) {
- return PERM_GROUP_REQUEST_RES.getOrDefault(groupName, 0);
+ return getRequest(groupName, ContextCompat.DEVICE_ID_DEFAULT);
+ }
+
+ /**
+ * The resource id for the request message for a permission group for a specific device
+ *
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getRequest(String groupName, int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return PERM_GROUP_REQUEST_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1031,7 +1224,22 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getBackgroundRequest(String groupName) {
- return PERM_GROUP_BACKGROUND_REQUEST_RES.getOrDefault(groupName, 0);
+ return getBackgroundRequest(groupName, ContextCompat.DEVICE_ID_DEFAULT);
+ }
+
+ /**
+ * The resource id for the background request message for a permission group for a specific
+ * device
+ *
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getBackgroundRequest(String groupName, int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return PERM_GROUP_BACKGROUND_REQUEST_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_BACKGROUND_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1049,7 +1257,20 @@ public final class Utils {
* @return The id or 0 if the permission group doesn't exist or have a message
*/
public static int getUpgradeRequest(String groupName) {
- return PERM_GROUP_UPGRADE_REQUEST_RES.getOrDefault(groupName, 0);
+ return getUpgradeRequest(groupName, ContextCompat.DEVICE_ID_DEFAULT);
+ }
+
+ /**
+ * The resource id for the upgrade request message for a permission group for a specific device.
+ * @param groupName Permission group name
+ * @return The id or 0 if the permission group doesn't exist or have a message
+ */
+ public static int getUpgradeRequest(String groupName, int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return PERM_GROUP_UPGRADE_REQUEST_RES.getOrDefault(groupName, 0);
+ } else {
+ return PERM_GROUP_UPGRADE_REQUEST_DEVICE_AWARE_RES.getOrDefault(groupName, 0);
+ }
}
/**
@@ -1062,6 +1283,42 @@ public final class Utils {
}
/**
+ * The resource id for the fine location request message for a specific device
+ * @return The id
+ */
+ public static int getFineLocationRequest(int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return R.string.permgrouprequest_fineupgrade;
+ } else {
+ return R.string.permgrouprequest_device_aware_fineupgrade;
+ }
+ }
+
+ /**
+ * The resource id for the coarse location request message for a specific device
+ * @return The id
+ */
+ public static int getCoarseLocationRequest(int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return R.string.permgrouprequest_coarselocation;
+ } else {
+ return R.string.permgrouprequest_device_aware_coarselocation;
+ }
+ }
+
+ /**
+ * The resource id for the get more photos request message for a specific device
+ * @return The id
+ */
+ public static int getMorePhotosRequest(int deviceId) {
+ if (deviceId == ContextCompat.DEVICE_ID_DEFAULT) {
+ return R.string.permgrouprequest_more_photos;
+ } else {
+ return R.string.permgrouprequest_device_aware_more_photos;
+ }
+ }
+
+ /**
* Returns a random session ID value that's guaranteed to not be {@code INVALID_SESSION_ID}.
*
* @return A valid session ID.
@@ -1249,10 +1506,8 @@ public final class Utils {
* Returns if a card should be shown if the sensor is blocked
**/
public static boolean shouldDisplayCardIfBlocked(@NonNull String permissionGroupName) {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_WARNING_BANNER_DISPLAY_ENABLED, true) && (
- CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName)
- || LOCATION.equals(permissionGroupName));
+ return CAMERA.equals(permissionGroupName) || MICROPHONE.equals(permissionGroupName)
+ || LOCATION.equals(permissionGroupName);
}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
index 1d5c9c9fa..5c02d49e3 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/AccessibilitySourceService.kt
@@ -35,6 +35,8 @@ import android.os.Bundle
import android.provider.DeviceConfig
import android.provider.Settings
import android.safetycenter.SafetyCenterManager
+import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID
+import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceData
import android.safetycenter.SafetySourceIssue
@@ -140,14 +142,12 @@ class AccessibilitySourceService(
sessionId = random.nextLong()
}
if (DEBUG) {
- Log.v(LOG_TAG, "safety center accessibility privacy job started.")
+ Log.d(LOG_TAG, "safety center accessibility privacy job started.")
}
interruptJobIfCanceled(cancel)
val a11yServiceList = getEnabledAccessibilityServices()
if (a11yServiceList.isEmpty()) {
- if (DEBUG) {
- Log.v(LOG_TAG, "accessibility services not enabled, job completed.")
- }
+ Log.d(LOG_TAG, "accessibility services not enabled, job completed.")
jobService.jobFinished(params, false)
jobService.clearJob()
return
@@ -167,7 +167,7 @@ class AccessibilitySourceService(
if (toBeNotifiedServices.isNotEmpty()) {
if (DEBUG) {
- Log.v(LOG_TAG, "sending an accessibility service notification")
+ Log.d(LOG_TAG, "sending an accessibility service notification")
}
val serviceToBeNotified: AccessibilityServiceInfo =
toBeNotifiedServices[random.nextInt(toBeNotifiedServices.size)]
@@ -239,7 +239,9 @@ class AccessibilitySourceService(
PendingIntent.FLAG_IMMUTABLE
)
)
- .setContentIntent(getSafetyCenterActivityIntent(context, uid, sessionId))
+ .setContentIntent(
+ getSafetyCenterActivityIntent(context, uid, sessionId, componentName)
+ )
val appNameExtras = Bundle()
appNameExtras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appLabel)
@@ -260,7 +262,7 @@ class AccessibilitySourceService(
markServiceAsNotified(ComponentName.unflattenFromString(serviceToBeNotified.id)!!)
if (DEBUG) {
- Log.v(LOG_TAG, "NOTIF_INTERACTION SEND metric, uid $uid session $sessionId")
+ Log.d(LOG_TAG, "NOTIF_INTERACTION SEND metric, uid $uid session $sessionId")
}
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION,
@@ -290,7 +292,7 @@ class AccessibilitySourceService(
sessionId: Long
): SafetySourceIssue {
val componentName = ComponentName.unflattenFromString(a11yService.id)!!
- val safetySourceIssueId = "accessibility_${componentName.flattenToString()}"
+ val safetySourceIssueId = getSafetySourceIssueId(componentName)
val pkgLabel = a11yService.resolveInfo.loadLabel(packageManager).toString()
val uid = a11yService.resolveInfo.serviceInfo.applicationInfo.uid
@@ -368,7 +370,7 @@ class AccessibilitySourceService(
val intent =
Intent(parentUserContext, AccessibilityRemoveAccessHandler::class.java).apply {
putExtra(Intent.EXTRA_COMPONENT_NAME, serviceComponentName)
- putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID, safetySourceIssueId)
+ putExtra(EXTRA_SAFETY_SOURCE_ISSUE_ID, safetySourceIssueId)
putExtra(Constants.EXTRA_SESSION_ID, sessionId)
putExtra(Intent.EXTRA_UID, uid)
flags = Intent.FLAG_RECEIVER_FOREGROUND
@@ -414,12 +416,15 @@ class AccessibilitySourceService(
private fun getSafetyCenterActivityIntent(
context: Context,
uid: Int,
- sessionId: Long
+ sessionId: Long,
+ componentName: ComponentName
): PendingIntent {
val intent = Intent(Intent.ACTION_SAFETY_CENTER)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtra(Constants.EXTRA_SESSION_ID, sessionId)
intent.putExtra(Intent.EXTRA_UID, uid)
+ intent.putExtra(EXTRA_SAFETY_SOURCE_ID, SC_ACCESSIBILITY_SOURCE_ID)
+ intent.putExtra(EXTRA_SAFETY_SOURCE_ISSUE_ID, getSafetySourceIssueId(componentName))
intent.putExtra(
Constants.EXTRA_PRIVACY_SOURCE,
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION__PRIVACY_SOURCE__A11Y_SERVICE
@@ -432,6 +437,10 @@ class AccessibilitySourceService(
)
}
+ private fun getSafetySourceIssueId(componentName: ComponentName): String {
+ return "accessibility_${componentName.flattenToString()}"
+ }
+
private fun sendIssuesToSafetyCenter(
a11yServiceList: List<AccessibilityServiceInfo>,
sessionId: Long,
@@ -441,9 +450,7 @@ class AccessibilitySourceService(
val dataBuilder = SafetySourceData.Builder()
pendingIssues.forEach { dataBuilder.addIssue(it) }
val safetySourceData = dataBuilder.build()
- if (DEBUG) {
- Log.v(LOG_TAG, "sending ${pendingIssues.size} issue to sc, data: $safetySourceData")
- }
+ Log.d(LOG_TAG, "a11y source sending ${pendingIssues.size} issue to sc")
safetyCenterManager.setSafetySourceData(
SC_ACCESSIBILITY_SOURCE_ID,
safetySourceData,
@@ -495,8 +502,10 @@ class AccessibilitySourceService(
installedServices[it]
}
- return enabledServices.filterNotNull()
+ val enabled3rdPartyServices = enabledServices.filterNotNull()
.filter { !it.isAccessibilityTool }
+ Log.d(LOG_TAG, "enabled a11y services count ${enabledServices.size}")
+ return enabled3rdPartyServices
}
/**
@@ -692,7 +701,7 @@ class AccessibilitySourceService(
refreshEvent: RefreshEvent
) {
if (DEBUG) {
- Log.v(LOG_TAG, "rescan and push event from safety center $refreshEvent")
+ Log.d(LOG_TAG, "rescan and push event from safety center $refreshEvent")
}
val safetyCenterEvent = getSafetyCenterEvent(refreshEvent, intent)
sendIssuesToSafetyCenter(safetyCenterEvent)
@@ -719,7 +728,7 @@ class AccessibilityPackageResetHandler : BroadcastReceiver() {
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
coroutineScope.launch(Dispatchers.Default) {
if (DEBUG) {
- Log.v(LOG_TAG, "package reset event occurred for ${data.schemeSpecificPart}")
+ Log.d(LOG_TAG, "package reset event occurred for ${data.schemeSpecificPart}")
}
AccessibilitySourceService(context).run {
removePackageState(data.schemeSpecificPart)
@@ -738,7 +747,7 @@ class AccessibilityNotificationDeleteHandler : BroadcastReceiver() {
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
coroutineScope.launch(Dispatchers.Default) {
if (DEBUG) {
- Log.v(LOG_TAG, "NOTIF_INTERACTION DISMISSED metric, uid $uid session $sessionId")
+ Log.d(LOG_TAG, "NOTIF_INTERACTION DISMISSED metric, uid $uid session $sessionId")
}
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_NOTIFICATION_INTERACTION,
@@ -767,7 +776,7 @@ class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
coroutineScope.launch(Dispatchers.Default) {
if (DEBUG) {
- Log.v(LOG_TAG, "disabling a11y service ${a11yService.flattenToShortString()}")
+ Log.d(LOG_TAG, "disabling a11y service ${a11yService.flattenToShortString()}")
}
AccessibilitySourceService.lock.withLock {
val accessibilityService = AccessibilitySourceService(context)
@@ -788,7 +797,7 @@ class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
)
}
val safetySourceIssueId = intent.getStringExtra(
- SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID
+ EXTRA_SAFETY_SOURCE_ISSUE_ID
)
val safetyEvent = builder.setSafetySourceIssueId(safetySourceIssueId)
.setSafetySourceIssueActionId(SC_ACCESSIBILITY_REMOVE_ACCESS_ACTION_ID)
@@ -796,7 +805,7 @@ class AccessibilityRemoveAccessHandler : BroadcastReceiver() {
accessibilityService.sendIssuesToSafetyCenter(a11yEnabledServices, safetyEvent)
}
if (DEBUG) {
- Log.v(LOG_TAG, "ISSUE_CARD_INTERACTION CTA1 metric, uid $uid session $sessionId")
+ Log.d(LOG_TAG, "ISSUE_CARD_INTERACTION CTA1 metric, uid $uid session $sessionId")
}
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION,
@@ -825,7 +834,7 @@ class AccessibilityWarningCardDismissalReceiver : BroadcastReceiver() {
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
coroutineScope.launch(Dispatchers.Default) {
if (DEBUG) {
- Log.v(LOG_TAG, "removing notification for ${componentName.flattenToShortString()}")
+ Log.d(LOG_TAG, "removing notification for ${componentName.flattenToShortString()}")
}
val accessibilityService = AccessibilitySourceService(context)
accessibilityService.removeAccessibilityNotification(componentName)
@@ -833,7 +842,7 @@ class AccessibilityWarningCardDismissalReceiver : BroadcastReceiver() {
}
if (DEBUG) {
- Log.v(LOG_TAG, "ISSUE_CARD_INTERACTION DISMISSED metric, uid $uid session $sessionId")
+ Log.d(LOG_TAG, "ISSUE_CARD_INTERACTION DISMISSED metric, uid $uid session $sessionId")
}
PermissionControllerStatsLog.write(
PRIVACY_SIGNAL_ISSUE_CARD_INTERACTION,
@@ -855,11 +864,11 @@ class AccessibilityOnBootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (!isAccessibilitySourceSupported() || isProfile(context)) {
- Log.v(LOG_TAG, "accessibility privacy job not supported, can't schedule the job")
+ Log.i(LOG_TAG, "accessibility privacy job not supported, can't schedule the job")
return
}
if (DEBUG) {
- Log.v(LOG_TAG, "scheduling safety center accessibility privacy source job")
+ Log.d(LOG_TAG, "scheduling safety center accessibility privacy source job")
}
val jobScheduler = getSystemServiceSafe(context, JobScheduler::class.java)
@@ -903,12 +912,12 @@ class AccessibilityJobService : JobService() {
Log.v(LOG_TAG, "accessibility privacy source job started.")
synchronized(mLock) {
if (mCurrentJob != null) {
- Log.v(LOG_TAG, "Accessibility privacy source job already running")
+ Log.i(LOG_TAG, "Accessibility privacy source job already running")
return false
}
if (!isAccessibilitySourceEnabled() ||
!isSafetyCenterEnabled(this@AccessibilityJobService)) {
- Log.v(LOG_TAG, "either privacy source or safety center is not enabled")
+ Log.i(LOG_TAG, "either privacy source or safety center is not enabled")
jobFinished(params, false)
mCurrentJob = null
return false
@@ -956,20 +965,20 @@ class SafetyCenterAccessibilityListener(val context: Context) :
override fun onAccessibilityServicesStateChanged(manager: AccessibilityManager) {
if (!isAccessibilityListenerEnabled()) {
- Log.v(LOG_TAG, "accessibility event occurred, listener not enabled.")
+ Log.i(LOG_TAG, "accessibility event occurred, listener not enabled.")
return
}
if (!isAccessibilitySourceEnabled() || !isSafetyCenterEnabled(context) ||
isProfile(context)) {
- Log.v(LOG_TAG, "accessibility event occurred, safety center feature not enabled.")
+ Log.i(LOG_TAG, "accessibility event occurred, safety center feature not enabled.")
return
}
val coroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
coroutineScope.launch(Dispatchers.Default) {
if (DEBUG) {
- Log.v(LOG_TAG, "processing accessibility event")
+ Log.d(LOG_TAG, "processing accessibility event")
}
AccessibilitySourceService.lock.withLock {
val a11ySourceService = AccessibilitySourceService(context)
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
index 91a043a6a..75a8d9eae 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerCheck.kt
@@ -282,7 +282,7 @@ internal class NotificationListenerCheckInternal(
sessionId = random.nextLong()
}
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"Found ${enabledComponents.size} enabled notification listeners. " +
"${notifiedComponents.size} already notified. ${unNotifiedComponents.size} " +
@@ -424,7 +424,7 @@ internal class NotificationListenerCheckInternal(
if (currentTimeMillis() - getLastNotificationShownTimeMillis() <
getInBetweenNotificationsMillis()) {
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"Notification not posted, within " +
"$DEFAULT_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS ms")
@@ -435,7 +435,7 @@ internal class NotificationListenerCheckInternal(
// Check for existing notification first, exit if one already present
if (getCurrentlyShownNotificationLocked() != null) {
if (DEBUG) {
- Log.v(TAG, "Notification not posted, previous notification has not been dismissed")
+ Log.d(TAG, "Notification not posted, previous notification has not been dismissed")
}
return
}
@@ -448,7 +448,7 @@ internal class NotificationListenerCheckInternal(
if (componentsInternal.isEmpty()) {
if (DEBUG) {
- Log.v(TAG, "Notification not posted, no unnotified enabled listeners")
+ Log.d(TAG, "Notification not posted, no unnotified enabled listeners")
}
return
}
@@ -456,7 +456,7 @@ internal class NotificationListenerCheckInternal(
componentToNotifyFor = componentsInternal[random.nextInt(componentsInternal.size)]
try {
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"Attempting to get PackageInfo for " + componentToNotifyFor.packageName)
}
@@ -504,8 +504,8 @@ internal class NotificationListenerCheckInternal(
sessionId: Long
) {
val pkgLabel =
- Utils.getApplicationLabel(parentUserContext, pkg.applicationInfo)
- val uid = pkg.applicationInfo.uid
+ Utils.getApplicationLabel(parentUserContext, pkg.applicationInfo!!)
+ val uid = pkg.applicationInfo!!.uid
val deletePendingIntent =
getNotificationDeletePendingIntent(parentUserContext, componentName, uid, sessionId)
@@ -546,7 +546,7 @@ internal class NotificationListenerCheckInternal(
componentName.flattenToString(), NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID, b.build())
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"Notification listener check notification shown with component=" +
"${componentName.flattenToString()}, uid=$uid, sessionId=$sessionId")
@@ -697,9 +697,9 @@ internal class NotificationListenerCheckInternal(
}
return null
}
- val pkgLabel = Utils.getApplicationLabel(parentUserContext, pkgInfo.applicationInfo)
+ val pkgLabel = Utils.getApplicationLabel(parentUserContext, pkgInfo.applicationInfo!!)
val safetySourceIssueId = getSafetySourceIssueIdFromComponentName(componentName)
- val uid = pkgInfo.applicationInfo.uid
+ val uid = pkgInfo.applicationInfo!!.uid
val disableNlsPendingIntent =
getDisableNlsPendingIntent(
@@ -954,7 +954,7 @@ class NotificationListenerCheckNotificationDeleteHandler : BroadcastReceiver() {
NotificationListenerCheckInternal(context, null).markComponentAsNotified(componentName)
}
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"Notification listener check notification declined with component=" +
"${componentName.flattenToString()} , uid=$uid, sessionId=$sessionId")
@@ -981,7 +981,7 @@ class DisableNotificationListenerComponentHandler : BroadcastReceiver() {
GlobalScope.launch(Default) {
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"DisableComponentHandler: disabling $componentName," +
"uid=$uid, sessionId=$sessionId")
@@ -1041,7 +1041,7 @@ class NotificationListenerActionCardDismissalReceiver : BroadcastReceiver() {
GlobalScope.launch(Default) {
if (DEBUG) {
- Log.v(
+ Log.d(
TAG,
"ActionCardDismissalReceiver: $componentName dismissed," +
"uid=$uid, sessionId=$sessionId")
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerPregrants.kt b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerPregrants.kt
index aaf2d32e6..4063ec8b2 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerPregrants.kt
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/NotificationListenerPregrants.kt
@@ -18,32 +18,34 @@ package com.android.permissioncontroller.privacysources
import android.content.Context
import androidx.annotation.VisibleForTesting
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
// (TODO:b/242573074) Remove for Android U.
class NotificationListenerPregrants(private val context: Context) {
@VisibleForTesting
val pregrantedPackagesDelegate = lazy {
hashSetOf(
- "android",
- "com.android.cellbroadcastreceiver",
- "com.android.server.telecom",
- "com.android.settings",
- "com.android.systemui",
- "com.android.launcher3",
- "com.android.dynsystem",
- "com.android.providers.settings",
- "com.android.inputdevices",
- "com.android.keychain",
- "com.android.localtransport",
- "com.android.wallpaperbackup",
- "com.android.location.fused"
- ).also {
- it.addAll(
- SafetyCenterResourcesContext(context)
- .getStringByName("config_NotificationListenerServicePregrants")
- .split(","))
- }
+ "android",
+ "com.android.cellbroadcastreceiver",
+ "com.android.server.telecom",
+ "com.android.settings",
+ "com.android.systemui",
+ "com.android.launcher3",
+ "com.android.dynsystem",
+ "com.android.providers.settings",
+ "com.android.inputdevices",
+ "com.android.keychain",
+ "com.android.localtransport",
+ "com.android.wallpaperbackup",
+ "com.android.location.fused"
+ )
+ .also {
+ it.addAll(
+ SafetyCenterResourcesApk(context)
+ .getStringByName("config_NotificationListenerServicePregrants")
+ .split(",")
+ )
+ }
}
val pregrantedPackages: Set<String> by pregrantedPackagesDelegate
}
diff --git a/PermissionController/src/com/android/permissioncontroller/privacysources/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/privacysources/TEST_MAPPING
index dc01ab3e2..3e8c5a19c 100644
--- a/PermissionController/src/com/android/permissioncontroller/privacysources/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/privacysources/TEST_MAPPING
@@ -36,5 +36,21 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsPermissionUiTestCases"
+ },
+ {
+ "name": "CtsPermissionTestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.NotificationListenerCheckTest"
+ },
+ {
+ "include-filter": "android.permission.cts.AccessibilityPrivacySourceTest"
+ }
+ ]
+ }
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING
index d7718a2f2..01d04bea0 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/role/TEST_MAPPING
@@ -21,7 +21,26 @@
"exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
},
{
- "exclude-annotation": "androidx.test.filters.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsRoleTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
}
]
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java
index 52471cb32..0e7e51a02 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppActivity.java
@@ -31,6 +31,7 @@ import com.android.permissioncontroller.DeviceUtils;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.role.ui.auto.AutoDefaultAppFragment;
import com.android.permissioncontroller.role.ui.handheld.HandheldDefaultAppFragment;
+import com.android.permissioncontroller.role.ui.wear.WearDefaultAppFragment;
import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
@@ -98,6 +99,8 @@ public class DefaultAppActivity extends SettingsActivity {
Fragment fragment;
if (DeviceUtils.isAuto(this)) {
fragment = AutoDefaultAppFragment.newInstance(roleName, user);
+ } else if (DeviceUtils.isWear(this)) {
+ fragment = WearDefaultAppFragment.Companion.newInstance(roleName, user);
} else {
fragment = HandheldDefaultAppFragment.newInstance(roleName, user);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListActivity.java
index d9cb6dca8..58f35705c 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListActivity.java
@@ -25,6 +25,7 @@ import com.android.permissioncontroller.DeviceUtils;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.role.ui.auto.AutoDefaultAppListFragment;
import com.android.permissioncontroller.role.ui.handheld.HandheldDefaultAppListFragment;
+import com.android.permissioncontroller.role.ui.wear.WearDefaultAppListFragment;
/**
* Activity for the list of default apps.
@@ -45,6 +46,8 @@ public class DefaultAppListActivity extends SettingsActivity {
Fragment fragment;
if (DeviceUtils.isAuto(this)) {
fragment = AutoDefaultAppListFragment.newInstance();
+ } else if (DeviceUtils.isWear(this)) {
+ fragment = WearDefaultAppListFragment.Companion.newInstance();
} else {
fragment = HandheldDefaultAppListFragment.newInstance();
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java
index 827d42643..eee30914d 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleActivity.java
@@ -302,4 +302,11 @@ public class RequestRoleActivity extends FragmentActivity {
}
return applicationInfo.uid;
}
+
+ @Override
+ protected void onNewIntent(@NonNull Intent intent) {
+ super.onNewIntent(intent);
+
+ Log.w(LOG_TAG, "Ignoring new intent: " + intent);
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
index a5bd90dc2..80834a3e2 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
@@ -457,7 +457,7 @@ public class RequestRoleFragment extends DialogFragment {
static void reportRequestResult(int requestingUid, String requestingPackageName,
String roleName, int qualifyingCount, int currentUid, String currentPackageName,
int grantedAnotherUid, String grantedAnotherPackageName, int result) {
- Log.v(LOG_TAG, "Role request result"
+ Log.i(LOG_TAG, "Role request result"
+ " requestingUid=" + requestingUid
+ " requestingPackageName=" + requestingPackageName
+ " roleName=" + roleName
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt
new file mode 100644
index 000000000..b843c38fe
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.UserHandle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.core.os.BundleCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.permission.ui.wear.setContent
+import com.android.permissioncontroller.role.ui.DefaultAppViewModel
+import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData
+import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModel
+import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModelFactory
+import com.android.role.controller.model.Role
+import com.android.role.controller.model.Roles
+
+/**
+ * Wear specific version of
+ * [com.android.permissioncontroller.role.ui.handheld.HandheldDefaultAppFragment]
+ */
+class WearDefaultAppFragment : Fragment() {
+ private lateinit var role: Role
+ private lateinit var viewModel: DefaultAppViewModel
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val roleName = arguments?.getString(Intent.EXTRA_ROLE_NAME) ?: ""
+ val user = arguments?.let {
+ BundleCompat.getParcelable(it, Intent.EXTRA_USER, UserHandle::class.java)!!
+ } ?: UserHandle.SYSTEM
+
+ val activity = requireActivity()
+ role = Roles.get(activity)[roleName] ?: let {
+ Log.e(TAG, "Unknown role: $roleName")
+ activity.finish()
+ return null
+ }
+
+ viewModel = ViewModelProvider(
+ this,
+ DefaultAppViewModel.Factory(role, user, activity.application)
+ ).get(DefaultAppViewModel::class.java)
+ viewModel.manageRoleHolderStateLiveData.observe(this, this::onManageRoleHolderStateChanged)
+
+ val confirmDialogViewModel = ViewModelProvider(
+ this,
+ DefaultAppConfirmDialogViewModelFactory()
+ ).get(DefaultAppConfirmDialogViewModel::class.java)
+
+ return ComposeView(activity).apply {
+ setContent {
+ WearDefaultAppScreen(
+ WearDefaultAppHelper(activity, user, role, viewModel, confirmDialogViewModel)
+ )
+ }
+ }
+ }
+
+ private fun onManageRoleHolderStateChanged(state: Int) {
+ val liveData = viewModel.manageRoleHolderStateLiveData
+ when (state) {
+ ManageRoleHolderStateLiveData.STATE_SUCCESS -> {
+ val packageName = liveData.lastPackageName
+ if (packageName != null) {
+ role.onHolderSelectedAsUser(packageName, liveData.lastUser, requireContext())
+ }
+ liveData.resetState()
+ }
+
+ ManageRoleHolderStateLiveData.STATE_FAILURE -> liveData.resetState()
+ }
+ }
+
+ companion object {
+ const val TAG = "WearDefaultAppFragment"
+
+ /**
+ * Creates a new instance of [WearDefaultAppFragment].
+ */
+ fun newInstance(roleName: String, user: UserHandle): WearDefaultAppFragment {
+ return WearDefaultAppFragment().apply {
+ arguments = Bundle().apply {
+ putString(Intent.EXTRA_ROLE_NAME, roleName)
+ putParcelable(Intent.EXTRA_USER, user)
+ }
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt
new file mode 100644
index 000000000..ef7ead985
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.os.UserHandle
+import android.util.Pair
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.role.ui.DefaultAppViewModel
+import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs
+import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModel
+import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils
+import com.android.role.controller.model.Role
+
+/**
+ * A helper class to retrieve default apps to [WearDefaultAppScreen].
+ */
+class WearDefaultAppHelper(
+ val context: Context,
+ val user: UserHandle,
+ val role: Role,
+ val viewModel: DefaultAppViewModel,
+ val confirmDialogViewModel: DefaultAppConfirmDialogViewModel
+) {
+ fun getTitle() = context.getString(role.labelResource)
+
+ fun getNonePreference(
+ qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>
+ ): WearRoleApplicationPreference? = if (role.shouldShowNone()) {
+ WearRoleApplicationPreference(
+ context = context,
+ label = context.getString(R.string.default_app_none),
+ checked = !hasHolderApplication(qualifyingApplications),
+ onDefaultCheckChanged = { _ ->
+ viewModel.setNoneDefaultApp()
+ }
+ ).apply {
+ icon = context.getDrawable(R.drawable.ic_remove_circle)
+ }
+ } else {
+ null
+ }
+
+ fun getPreferences(
+ qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>
+ ): List<WearRoleApplicationPreference> {
+ return qualifyingApplications.map { pair ->
+ WearRoleApplicationPreference(
+ context = context,
+ label = Utils.getFullAppLabel(pair.first, context),
+ checked = pair.second,
+ onDefaultCheckChanged = { _ ->
+ run {
+ val packageName = pair.first.packageName
+ val confirmationMessage = RoleUiBehaviorUtils.getConfirmationMessage(
+ role, packageName, context
+ )
+ if (confirmationMessage != null) {
+ showConfirmDialog(packageName, confirmationMessage.toString())
+ } else {
+ setDefaultApp(packageName)
+ }
+ }
+ }
+ ).apply {
+ icon = pair.first.loadIcon(context.packageManager)
+ }.let {
+ RoleUiBehaviorUtils.prepareApplicationPreferenceAsUser(
+ role, it, pair.first, user, context
+ )
+ return@map it
+ }
+ }.toList()
+ }
+
+ private fun showConfirmDialog(packageName: String, message: String) {
+ confirmDialogViewModel.confirmDialogArgs = ConfirmDialogArgs(
+ message = message,
+ onOkButtonClick = {
+ setDefaultApp(packageName)
+ dismissConfirmDialog()
+ },
+ onCancelButtonClick = {
+ dismissConfirmDialog()
+ }
+ )
+ confirmDialogViewModel.showConfirmDialogLiveData.value = true
+ }
+
+ private fun dismissConfirmDialog() {
+ confirmDialogViewModel.confirmDialogArgs = null
+ confirmDialogViewModel.showConfirmDialogLiveData.value = false
+ }
+ private fun setDefaultApp(packageName: String) {
+ viewModel.setDefaultApp(packageName)
+ }
+
+ fun getDescription() = context.getString(role.descriptionResource)
+
+ private fun hasHolderApplication(
+ qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>
+ ): Boolean = qualifyingApplications.map { it.second }.find { true } ?: false
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListFragment.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListFragment.kt
new file mode 100644
index 000000000..7b701fe58
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListFragment.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.android.permissioncontroller.role.ui.DefaultAppListViewModel
+
+class WearDefaultAppListFragment : Fragment() {
+ companion object {
+ /**
+ * @return a new instance of [WearDefaultAppListFragment].
+ */
+ fun newInstance(): WearDefaultAppListFragment {
+ return WearDefaultAppListFragment()
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ val context = requireContext()
+ val viewModel = ViewModelProvider(this).get(DefaultAppListViewModel::class.java)
+ val user = viewModel.user
+ return ComposeView(requireContext()).apply {
+ setContent {
+ WearDefaultAppListScreen(
+ WearDefaultAppListHelper(context, user),
+ viewModel.liveData
+ )
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt
new file mode 100644
index 000000000..baef22630
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListHelper.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.content.Context
+import android.os.UserHandle
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.utils.Utils
+import com.android.permissioncontroller.role.ui.DefaultAppActivity
+import com.android.permissioncontroller.role.ui.RoleItem
+import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils
+import com.android.role.controller.model.Roles
+
+/**
+ * A helper class to retrieve default apps to [WearDefaultAppListScreen].
+ */
+class WearDefaultAppListHelper(
+ val context: Context,
+ val user: UserHandle
+) {
+ fun getPreferences(defaultRole: List<RoleItem>): List<WearRolePreference> {
+ return defaultRole.map { roleItem ->
+ WearRolePreference(
+ context = context,
+ label = context.getString(roleItem.role.shortLabelResource),
+ onDefaultClicked = {
+ run {
+ val roleName: String = roleItem.role.name
+ val role = Roles.get(context)[roleName]
+ var intent =
+ RoleUiBehaviorUtils.getManageIntentAsUser(role!!, user, context)
+ if (intent == null) {
+ intent = DefaultAppActivity.createIntent(roleName, user, context)
+ }
+ context.startActivity(intent)
+ }
+ }
+ ).apply {
+ val holderApplicationInfos = roleItem.holderApplicationInfos
+ if (holderApplicationInfos.isEmpty()) {
+ icon = null
+ summary = context.getString(R.string.default_app_none)
+ } else {
+ val holderApplicationInfo = holderApplicationInfos[0]
+ icon = Utils.getBadgedIcon(context, holderApplicationInfo)
+ summary = Utils.getAppLabel(holderApplicationInfo, context)
+ }
+ }.let {
+ RoleUiBehaviorUtils.preparePreferenceAsUser(roleItem.role, it, user, context)
+ return@map it
+ }
+ }.toList()
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt
new file mode 100644
index 000000000..b78f41284
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.LiveData
+import androidx.wear.compose.material.Text
+import com.android.permissioncontroller.R
+import com.android.permissioncontroller.permission.ui.wear.elements.Chip
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.elements.chipDefaultColors
+import com.android.permissioncontroller.permission.ui.wear.elements.chipDisabledColors
+import com.android.permissioncontroller.role.ui.RoleItem
+
+@Composable
+fun WearDefaultAppListScreen(
+ helper: WearDefaultAppListHelper,
+ defaultAppsLiveData: LiveData<List<RoleItem>>,
+) {
+ val defaultAppsState = defaultAppsLiveData.observeAsState(emptyList())
+ val defaultApps: List<RoleItem> by remember {
+ derivedStateOf {
+ defaultAppsState.value
+ }
+ }
+ val preferences = helper.getPreferences(defaultApps)
+ var isLoading by remember { mutableStateOf(true) }
+
+ ScrollableScreen(
+ title = stringResource(R.string.default_apps),
+ isLoading = isLoading
+ ) {
+ if (preferences.isEmpty()) {
+ item {
+ Text(stringResource(R.string.no_default_apps))
+ }
+ return@ScrollableScreen
+ }
+ preferences.forEach { pref ->
+ item {
+ Chip(
+ label = pref.label,
+ icon = pref.icon,
+ colors = if (pref.isEnabled()) {
+ chipDefaultColors()
+ } else {
+ chipDisabledColors()
+ },
+ secondaryLabel = pref.summary?.toString(),
+ onClick = pref.getOnClicked(),
+ modifier = Modifier.fillMaxWidth(),
+ labelMaxLines = Int.MAX_VALUE,
+ secondaryLabelMaxLines = Integer.MAX_VALUE
+ )
+ }
+ }
+ }
+ if (isLoading && defaultApps.isNotEmpty()) {
+ isLoading = false
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt
new file mode 100644
index 000000000..33de3a2be
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.content.pm.ApplicationInfo
+import android.util.Pair
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.material.ToggleChipDefaults
+import com.android.permissioncontroller.permission.ui.wear.elements.AlertDialog
+import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter
+import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
+import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.elements.toggleChipDisabledColors
+import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs
+
+@Composable
+fun WearDefaultAppScreen(
+ helper: WearDefaultAppHelper
+) {
+ val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList())
+ val showConfirmDialog =
+ helper.confirmDialogViewModel.showConfirmDialogLiveData.observeAsState(false)
+ var isLoading by remember { mutableStateOf(true) }
+ Box {
+ WearDefaultAppContent(isLoading, roleLiveData.value, helper)
+ ConfirmDialog(
+ showDialog = showConfirmDialog.value,
+ args = helper.confirmDialogViewModel.confirmDialogArgs
+ )
+ }
+ if (isLoading && roleLiveData.value.isNotEmpty()) {
+ isLoading = false
+ }
+}
+
+@Composable
+private fun WearDefaultAppContent(
+ isLoading: Boolean,
+ qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>,
+ helper: WearDefaultAppHelper
+) {
+ ScrollableScreen(
+ title = helper.getTitle(),
+ isLoading = isLoading
+ ) {
+ helper.getNonePreference(qualifyingApplications)?.let{
+ item {
+ ToggleChip(
+ label = it.label,
+ icon = it.icon,
+ checked = it.checked,
+ onCheckedChanged = it.onDefaultCheckChanged,
+ toggleControl = ToggleChipToggleControl.Radio,
+ labelMaxLine = Integer.MAX_VALUE
+ )
+ }
+ }
+ for (pref in helper.getPreferences(qualifyingApplications)) {
+ item {
+ ToggleChip(
+ label = pref.label,
+ icon = pref.icon,
+ colors = if (pref.isEnabled()) {
+ ToggleChipDefaults.toggleChipColors()
+ } else {
+ toggleChipDisabledColors()
+ },
+ secondaryLabel = pref.summary?.toString(),
+ checked = pref.checked,
+ onCheckedChanged = pref.getOnCheckChanged(),
+ toggleControl = ToggleChipToggleControl.Radio,
+ labelMaxLine = Integer.MAX_VALUE,
+ secondaryLabelMaxLine = Integer.MAX_VALUE
+ )
+ }
+ }
+
+ item {
+ ListFooter(
+ description = helper.getDescription()
+ )
+ }
+ }
+}
+
+@Composable
+private fun ConfirmDialog(
+ showDialog: Boolean,
+ args: ConfirmDialogArgs?
+) {
+ args?.let {
+ AlertDialog(
+ showDialog = showDialog,
+ message = it.message,
+ onOKButtonClick = it.onOkButtonClick,
+ onCancelButtonClick = it.onCancelButtonClick,
+ scalingLazyListState = rememberScalingLazyListState()
+ )
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
new file mode 100644
index 000000000..8b23567f9
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.app.admin.DevicePolicyManager
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import androidx.preference.TwoStatePreference
+import com.android.permissioncontroller.role.ui.RoleApplicationPreference
+
+/**
+ * Role application preference for Wear.
+ * The preference is only used to hand over the properties to ToggleChip.
+ */
+class WearRoleApplicationPreference(
+ context: Context,
+ val label: String,
+ val checked: Boolean,
+ val onDefaultCheckChanged: (Boolean) -> Unit = {},
+ private var restriction: String? = null
+) : TwoStatePreference(context), RoleApplicationPreference {
+ fun getOnCheckChanged(): (Boolean) -> Unit =
+ restriction?.let {
+ return { _ ->
+ context.startActivity(
+ Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS)
+ .putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction)
+ )
+ }
+ } ?: onDefaultCheckChanged
+
+ override fun setUserRestriction(userRestriction: String?) {
+ restriction = userRestriction
+ setEnabled(restriction == null)
+ }
+
+ override fun asTwoStatePreference(): TwoStatePreference {
+ return this
+ }
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
new file mode 100644
index 000000000..7796f6df6
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 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.ui.wear
+
+import android.app.admin.DevicePolicyManager
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import androidx.preference.Preference
+import com.android.permissioncontroller.role.ui.RolePreference
+import com.android.permissioncontroller.role.ui.TwoTargetPreference.OnSecondTargetClickListener
+import com.android.settingslib.widget.TwoTargetPreference
+
+/**
+ * Role preference for Wear.
+ * The preference is only used to hand over the properties to Chip.
+ */
+class WearRolePreference(
+ context: Context,
+ val label: String,
+ val onDefaultClicked: () -> Unit = {},
+ private var restriction: String? = null
+) : TwoTargetPreference(context), RolePreference {
+
+ override fun setOnSecondTargetClickListener(listener: OnSecondTargetClickListener?) {
+ // no-op
+ }
+
+ override fun setUserRestriction(userRestriction: String?) {
+ restriction = userRestriction
+ setEnabled(restriction == null)
+ }
+
+ override fun asPreference(): Preference {
+ return this
+ }
+
+ fun getOnClicked(): () -> Unit =
+ restriction?.let {
+ return {
+ context.startActivity(
+ Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS)
+ .putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction)
+ )
+ }
+ } ?: onDefaultClicked
+} \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/model/DefaultAppConfirmDialogViewModel.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/model/DefaultAppConfirmDialogViewModel.kt
new file mode 100644
index 000000000..27b5b39ad
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/model/DefaultAppConfirmDialogViewModel.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 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.ui.wear.model
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+/**
+ * ViewModel for a default app confirm dialog.
+ */
+class DefaultAppConfirmDialogViewModel : ViewModel() {
+ /** A livedata which stores whether confirmation dialog is visible. */
+ val showConfirmDialogLiveData = MutableLiveData<Boolean>()
+
+ /** Arguments for a confirmation dialog. */
+ var confirmDialogArgs: ConfirmDialogArgs? = null
+
+ init {
+ showConfirmDialogLiveData.value = false
+ }
+}
+
+/**
+ * Factory for a DefaultAppConfirmDialogViewModel
+ */
+class DefaultAppConfirmDialogViewModelFactory : ViewModelProvider.Factory {
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ @Suppress("UNCHECKED_CAST")
+ return DefaultAppConfirmDialogViewModel() as T
+ }
+}
+
+/**
+ * Data class for arguments of a default app confirm dialog.
+ */
+data class ConfirmDialogArgs(
+ val message: String,
+ val onOkButtonClick: () -> Unit,
+ val onCancelButtonClick: () -> Unit
+) \ No newline at end of file
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java
index e959d20be..d23a23f7c 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java
@@ -39,6 +39,8 @@ import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
+import java.time.Duration;
+
/**
* Uses {@link android.app.job.JobScheduler} to schedule periodic calls to {@link
* SafetyCenterManager#refreshSafetySources} after boot completed if safety center is already
@@ -46,7 +48,6 @@ import com.android.modules.utils.build.SdkLevel;
*
* <p>The job waits until the device is in idle mode to minimize impact on system health.
*/
-// TODO(b/243493200): Add tests
public final class SafetyCenterBackgroundRefreshJobService extends JobService {
private static final String TAG = "SafetyCenterBackgroundR";
@@ -76,7 +77,7 @@ public final class SafetyCenterBackgroundRefreshJobService extends JobService {
Context context, @Nullable String actionString) {
if (!isActionStringValid(actionString)) {
- Log.v(TAG, "Ignoring a " + actionString + " broadcast.");
+ Log.i(TAG, "Ignoring a " + actionString + " broadcast.");
return;
}
@@ -94,7 +95,7 @@ public final class SafetyCenterBackgroundRefreshJobService extends JobService {
}
if (!safetyCenterManager.isSafetyCenterEnabled()) {
- Log.v(
+ Log.i(
TAG,
"Received a "
+ actionString
@@ -104,30 +105,26 @@ public final class SafetyCenterBackgroundRefreshJobService extends JobService {
return;
}
+ Duration periodicBackgroundRefreshInterval =
+ SafetyCenterJobServiceFlags.getPeriodicBackgroundRefreshInterval();
JobInfo jobInfo =
new JobInfo.Builder(
SAFETY_CENTER_BACKGROUND_REFRESH_JOB_ID,
new ComponentName(
context, SafetyCenterBackgroundRefreshJobService.class))
.setRequiresDeviceIdle(true)
- .setRequiresCharging(
- SafetyCenterJobServiceFlags.getBackgroundRefreshRequiresCharging())
- .setPeriodic(
- SafetyCenterJobServiceFlags.getPeriodicBackgroundRefreshInterval()
- .toMillis())
+ .setRequiresCharging(true)
+ .setPeriodic(periodicBackgroundRefreshInterval.toMillis())
.build();
Log.v(
TAG,
- "Scheduling a periodic background refresh with "
- + ", interval="
- + jobInfo.getIntervalMillis()
- + "requires charging="
- + jobInfo.isRequireCharging());
+ "Scheduling a periodic background refresh with interval="
+ + periodicBackgroundRefreshInterval);
int scheduleResult = jobScheduler.schedule(jobInfo);
if (scheduleResult != RESULT_SUCCESS) {
- Log.e(
+ Log.w(
TAG,
"Could not schedule the background refresh job, scheduleResult="
+ scheduleResult);
@@ -138,7 +135,7 @@ public final class SafetyCenterBackgroundRefreshJobService extends JobService {
public boolean onStartJob(JobParameters params) {
// background thread not required, PC APK makes all API calls in main thread
if (!SafetyCenterJobServiceFlags.areBackgroundRefreshesEnabled()) {
- Log.v(TAG, "Background refreshes are not enabled, skipping job.");
+ Log.i(TAG, "Background refreshes are not enabled, skipping job.");
return false; // job is no longer running
}
SafetyCenterManager safetyCenterManager = this.getSystemService(SafetyCenterManager.class);
@@ -147,7 +144,7 @@ public final class SafetyCenterBackgroundRefreshJobService extends JobService {
return false; // job is no longer running
}
if (!safetyCenterManager.isSafetyCenterEnabled()) {
- Log.v(TAG, "Safety center is not enabled, skipping job.");
+ Log.i(TAG, "Safety center is not enabled, skipping job.");
return false; // job is no longer running
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterJobServiceFlags.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterJobServiceFlags.java
index bdca4d77d..23e048e7b 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterJobServiceFlags.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterJobServiceFlags.java
@@ -26,8 +26,6 @@ public class SafetyCenterJobServiceFlags {
private static final Duration DEFAULT_PERIODIC_BACKGROUND_REFRESH_INTERVAL = Duration.ofDays(1);
private static final String PROPERTY_BACKGROUND_REFRESH_IS_ENABLED =
"safety_center_background_refresh_is_enabled";
- private static final String PROPERTY_BACKGROUND_REFRESH_REQUIRES_CHARGING =
- "safety_center_background_requires_charging";
private static final String PROPERTY_PERIODIC_BACKGROUND_REFRESH_INTERVAL_MILLIS =
"safety_center_periodic_background_interval_millis";
@@ -47,15 +45,4 @@ public class SafetyCenterJobServiceFlags {
PROPERTY_PERIODIC_BACKGROUND_REFRESH_INTERVAL_MILLIS,
DEFAULT_PERIODIC_BACKGROUND_REFRESH_INTERVAL.toMillis()));
}
-
- /**
- * Returns whether we should constrain background refresh jobs to only run when the device is
- * charging.
- */
- static boolean getBackgroundRefreshRequiresCharging() {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_BACKGROUND_REFRESH_REQUIRES_CHARGING,
- true);
- }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt
index 8e5e63452..88dd8a6e3 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterSearchIndexablesProvider.kt
@@ -52,7 +52,7 @@ import com.android.permissioncontroller.safetycenter.ui.model.PrivacyControlsVie
import com.android.safetycenter.internaldata.SafetyCenterBundles
import com.android.safetycenter.internaldata.SafetyCenterEntryId
import com.android.safetycenter.internaldata.SafetyCenterIds
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
/** [android.provider.SearchIndexablesProvider] for Safety Center. */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@@ -67,7 +67,7 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
val context = requireContext()
val safetyCenterManager =
context.getSystemService(SafetyCenterManager::class.java) ?: return cursor
- val resourcesContext = SafetyCenterResourcesContext(context)
+ val safetyCenterResourcesApk = SafetyCenterResourcesApk(context)
val screenTitle = context.getString(R.string.safety_center_dashboard_page_title)
@@ -76,7 +76,11 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
SdkLevel.isAtLeastU() &&
safetySourcesGroup.type == SAFETY_SOURCES_GROUP_TYPE_STATEFUL
) {
- cursor.addSafetySourcesGroupRow(safetySourcesGroup, resourcesContext, screenTitle)
+ cursor.addSafetySourcesGroupRow(
+ safetySourcesGroup,
+ safetyCenterResourcesApk,
+ screenTitle
+ )
}
safetySourcesGroup.safetySources
.asSequence()
@@ -85,7 +89,7 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
cursor.addSafetySourceRow(
context,
safetySource,
- resourcesContext,
+ safetyCenterResourcesApk,
safetyCenterManager,
screenTitle
)
@@ -139,11 +143,12 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
private fun MatrixCursor.addSafetySourcesGroupRow(
safetySourcesGroups: SafetySourcesGroup,
- resourcesContext: SafetyCenterResourcesContext,
+ safetyCenterResourcesApk: SafetyCenterResourcesApk,
screenTitle: String,
) {
val groupTitle =
- resourcesContext.getNotEmptyStringOrNull(safetySourcesGroups.titleResId) ?: return
+ safetyCenterResourcesApk.getNotEmptyStringOrNull(safetySourcesGroups.titleResId)
+ ?: return
newRow()
.add(COLUMN_RANK, 0)
@@ -157,11 +162,12 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
private fun MatrixCursor.addSafetySourceRow(
context: Context,
safetySource: SafetySource,
- resourcesContext: SafetyCenterResourcesContext,
+ safetyCenterResourcesApk: SafetyCenterResourcesApk,
safetyCenterManager: SafetyCenterManager,
screenTitle: String,
) {
- val searchTerms = resourcesContext.getNotEmptyStringOrNull(safetySource.searchTermsResId)
+ val searchTerms =
+ safetyCenterResourcesApk.getNotEmptyStringOrNull(safetySource.searchTermsResId)
var isPersonalEntryAdded = false
var isWorkEntryAdded = false
@@ -194,19 +200,19 @@ class SafetyCenterSearchIndexablesProvider : BaseSearchIndexablesProvider() {
}
if (!isPersonalEntryAdded) {
- resourcesContext.getNotEmptyStringOrNull(safetySource.titleResId)?.let {
+ safetyCenterResourcesApk.getNotEmptyStringOrNull(safetySource.titleResId)?.let {
addIndexableRow(title = it, isWorkProfile = false)
}
}
if (!isWorkEntryAdded && safetySource.profile == SafetySource.PROFILE_ALL) {
- resourcesContext.getNotEmptyStringOrNull(safetySource.titleForWorkResId)?.let {
+ safetyCenterResourcesApk.getNotEmptyStringOrNull(safetySource.titleForWorkResId)?.let {
addIndexableRow(title = it, isWorkProfile = true)
}
}
}
- private fun Context.getNotEmptyStringOrNull(resId: Int): String? =
+ private fun SafetyCenterResourcesApk.getNotEmptyStringOrNull(resId: Int): String? =
if (resId != Resources.ID_NULL) {
getString(resId).takeIf { it.isNotEmpty() }
} else {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt
new file mode 100644
index 000000000..077ccfa2d
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/EntriesTopPaddingPreference.kt
@@ -0,0 +1,13 @@
+package com.android.permissioncontroller.safetycenter.ui
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.preference.Preference
+import com.android.permissioncontroller.R
+
+class EntriesTopPaddingPreference(context: Context, attrs: AttributeSet) :
+ Preference(context, attrs) {
+ init {
+ layoutResource = R.layout.preference_entries_top_padding
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt
index 2bc83eb10..c83737649 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt
@@ -91,9 +91,11 @@ class IssueCardAnimator(val callback: AnimationCallback) {
// view groups.
defaultIssueContentGroup.visibility = View.INVISIBLE
- // These two views are outside of the group since their visibility must be set
+ // These views are outside of the group since their visibility must be set
// independently of the rest of the group, and some frustrating constraints of
// constraint layout's behavior. See b/242705351 for context.
+ makeInvisibleIfVisible(holder.findViewById(R.id.issue_card_attribution_title))
+ makeInvisibleIfVisible(holder.findViewById(R.id.issue_card_dismiss_btn))
makeInvisibleIfVisible(holder.findViewById(R.id.issue_card_subtitle))
makeInvisibleIfVisible(holder.findViewById(R.id.issue_card_protected_by_android))
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardPreference.java
index c56cce0a5..7622270b9 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardPreference.java
@@ -30,6 +30,7 @@ import android.os.Bundle;
import android.safetycenter.SafetyCenterIssue;
import android.text.TextUtils;
import android.util.Log;
+import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
@@ -134,9 +135,7 @@ public class IssueCardPreference extends Preference implements ComparablePrefere
configureSafetyProtectionView(holder);
maybeStartResolutionAnimation(holder);
- mSafetyCenterViewModel
- .getInteractionLogger()
- .recordIssueViewed(mIssue, mIsDismissed);
+ mSafetyCenterViewModel.getInteractionLogger().recordIssueViewed(mIssue, mIsDismissed);
}
private void maybeDisplayText(@Nullable CharSequence maybeText, TextView textView) {
@@ -424,8 +423,14 @@ public class IssueCardPreference extends Preference implements ComparablePrefere
ActionButtonBuilder(SafetyCenterIssue.Action action, Context context) {
mAction = action;
mContext = context;
- mContextThemeWrapper =
- new ContextThemeWrapper(context, R.style.Theme_MaterialComponents_DayNight);
+
+ TypedValue buttonThemeValue = new TypedValue();
+ mContext.getTheme()
+ .resolveAttribute(
+ R.attr.scActionButtonTheme,
+ buttonThemeValue,
+ /* resolveRefs= */ false);
+ mContextThemeWrapper = new ContextThemeWrapper(context, buttonThemeValue.data);
}
public ActionButtonBuilder setIndex(int index) {
@@ -540,9 +545,11 @@ public class IssueCardPreference extends Preference implements ComparablePrefere
return;
}
- int margin =
- mContext.getResources()
- .getDimensionPixelSize(R.dimen.sc_action_button_list_margin);
+ int marginRes =
+ mIsLargeScreen
+ ? R.dimen.sc_action_button_list_margin_large_screen
+ : R.dimen.sc_action_button_list_margin;
+ int margin = mContext.getResources().getDimensionPixelSize(marginRes);
Space space = new Space(mContext);
space.setLayoutParams(new ViewGroup.LayoutParams(margin, margin));
buttonList.addView(space);
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
index 54ba9560f..62c46dfc4 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/PrivacySubpageFragment.kt
@@ -81,7 +81,7 @@ class PrivacySubpageFragment : SafetyCenterFragment() {
}
override fun renderSafetyCenterData(uiData: SafetyCenterUiData?) {
- Log.d(TAG, "renderSafetyCenterEntryGroup called with $uiData")
+ Log.v(TAG, "renderSafetyCenterEntryGroup called with $uiData")
val entryGroup = uiData?.getMatchingGroup(PRIVACY_SOURCES_GROUP_ID)
if (entryGroup == null) {
Log.w(
@@ -118,7 +118,7 @@ class PrivacySubpageFragment : SafetyCenterFragment() {
}
private fun updateSafetyCenterEntries(entryGroup: SafetyCenterEntryGroup) {
- Log.d(TAG, "updateSafetyCenterEntries called with $entryGroup")
+ Log.v(TAG, "updateSafetyCenterEntries called with $entryGroup")
subpageGenericEntryGroup.removeAll()
subpageControlsExtraEntryGroup.removeAll()
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java
index 8f31da828..c07563a21 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterActivity.java
@@ -30,12 +30,14 @@ import static com.android.permissioncontroller.safetycenter.SafetyCenterConstant
import android.app.ActionBar;
import android.content.Intent;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.provider.Settings;
import android.safetycenter.SafetyCenterManager;
import android.safetycenter.config.SafetyCenterConfig;
import android.safetycenter.config.SafetySource;
import android.safetycenter.config.SafetySourcesGroup;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -107,7 +109,30 @@ public final class SafetyCenterActivity extends CollapsingToolbarBaseActivity {
.commitNow();
}
+ configureHomeButton();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ maybeRedirectIfDisabled();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ // We don't set configChanges, but small screen size changes may still be delivered here.
+ super.onConfigurationChanged(newConfig);
+ configureHomeButton();
+ }
+
+ /** Decide whether a home/back button should be shown or not. */
+ private void configureHomeButton() {
ActionBar actionBar = getActionBar();
+ Fragment frag = getSupportFragmentManager().findFragmentById(R.id.content_frame);
+ if (actionBar == null || frag == null) {
+ return;
+ }
+
// Only the homepage can be considered a "second layer" page as it's the only one that
// can be reached from the Settings menu. The other pages are only reachable using
// a direct intent (e.g. notification, "first layer") and/or by navigating within Safety
@@ -115,30 +140,33 @@ public final class SafetyCenterActivity extends CollapsingToolbarBaseActivity {
// Note that the homepage can also be a "first layer" page, but that would only happen
// if the activity is not embedded.
boolean isSecondLayerPage = frag instanceof SafetyCenterScrollWrapperFragment;
- if (actionBar != null
- && ActivityEmbeddingUtils.shouldHideNavigateUpButton(this, isSecondLayerPage)) {
+ if (ActivityEmbeddingUtils.shouldHideNavigateUpButton(this, isSecondLayerPage)) {
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setHomeButtonEnabled(false);
}
}
- @Override
- protected void onStart() {
- super.onStart();
- maybeRedirectIfDisabled();
- }
-
private boolean maybeRedirectIfDisabled() {
if (mSafetyCenterManager == null || !mSafetyCenterManager.isSafetyCenterEnabled()) {
Log.w(TAG, "Safety Center disabled, redirecting to settings page");
startActivity(
- new Intent(Settings.ACTION_SETTINGS).addFlags(FLAG_ACTIVITY_FORWARD_RESULT));
+ new Intent(getActionToRedirectWhenDisabled())
+ .addFlags(FLAG_ACTIVITY_FORWARD_RESULT));
finish();
return true;
}
return false;
}
+ private String getActionToRedirectWhenDisabled() {
+ boolean isPrivacyControls =
+ TextUtils.equals(getIntent().getAction(), PRIVACY_CONTROLS_ACTION);
+ if (isPrivacyControls) {
+ return Settings.ACTION_PRIVACY_SETTINGS;
+ }
+ return Settings.ACTION_SETTINGS;
+ }
+
private boolean maybeRedirectIntoTwoPaneSettings() {
return shouldUseTwoPaneSettings() && tryRedirectTwoPaneSettings();
}
@@ -192,7 +220,7 @@ public final class SafetyCenterActivity extends CollapsingToolbarBaseActivity {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
long sessionId =
intent.getLongExtra(Constants.EXTRA_SESSION_ID, Constants.INVALID_SESSION_ID);
- Log.v(
+ Log.i(
TAG,
"privacy source notification metric, source "
+ privacySource
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
index 940cb2f69..874e3c750 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterDashboardFragment.java
@@ -38,18 +38,22 @@ import android.safetycenter.SafetyCenterIssue;
import android.safetycenter.SafetyCenterStaticEntry;
import android.safetycenter.SafetyCenterStaticEntryGroup;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
+import androidx.recyclerview.widget.RecyclerView;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterUiData;
import com.android.permissioncontroller.safetycenter.ui.model.StatusUiData;
import com.android.safetycenter.internaldata.SafetyCenterBundles;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import kotlin.Unit;
@@ -113,6 +117,7 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
mIssuesGroup = getPreferenceScreen().findPreference(ISSUES_GROUP_KEY);
mEntriesGroup = getPreferenceScreen().findPreference(ENTRIES_GROUP_KEY);
mStaticEntriesGroup = getPreferenceScreen().findPreference(STATIC_ENTRIES_GROUP_KEY);
+
if (mIsQuickSettingsFragment) {
getPreferenceScreen().removePreference(mEntriesGroup);
mEntriesGroup = null;
@@ -126,6 +131,19 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
prerenderCurrentSafetyCenterData();
}
+ @Override
+ public RecyclerView onCreateRecyclerView(
+ LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ RecyclerView recyclerView =
+ super.onCreateRecyclerView(inflater, parent, savedInstanceState);
+
+ if (mIsQuickSettingsFragment) {
+ recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
+ recyclerView.setVerticalScrollBarEnabled(false);
+ }
+ return recyclerView;
+ }
+
// Set the default divider line between preferences to be transparent
@Override
public void setDivider(Drawable divider) {
@@ -162,10 +180,10 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
private void updateStatus(StatusUiData statusUiData) {
if (mIsQuickSettingsFragment) {
- SafetyCenterResourcesContext safetyCenterResourcesContext =
- new SafetyCenterResourcesContext(requireContext());
+ SafetyCenterResourcesApk safetyCenterResourcesApk =
+ new SafetyCenterResourcesApk(requireContext());
boolean hasPendingActions =
- safetyCenterResourcesContext
+ safetyCenterResourcesApk
.getStringByName("overall_severity_level_ok_review_summary")
.equals(statusUiData.getOriginalSummary().toString());
@@ -180,8 +198,7 @@ public final class SafetyCenterDashboardFragment extends SafetyCenterFragment {
if (uiData == null) return;
SafetyCenterData data = uiData.getSafetyCenterData();
- Log.i(TAG, String.format("renderSafetyCenterData called with: %s", data));
-
+ Log.v(TAG, String.format("renderSafetyCenterData called with: %s", data));
Context context = getContext();
if (context == null) {
return;
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
index c435a0f1a..6f146e48c 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
@@ -32,7 +32,7 @@ import com.android.permissioncontroller.safetycenter.ui.ParsedSafetyCenterIntent
import com.android.permissioncontroller.safetycenter.ui.model.LiveSafetyCenterViewModelFactory
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterUiData
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterViewModel
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
/** A base fragment that represents a page in Safety Center. */
@RequiresApi(TIRAMISU)
@@ -72,7 +72,7 @@ abstract class SafetyCenterFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
sameTaskSourceIds =
- SafetyCenterResourcesContext(requireContext())
+ SafetyCenterResourcesApk(requireContext())
.getStringByName("config_same_task_safety_source_ids")
.split(",")
safetyCenterSessionId = requireArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
index f69746e39..8804b3c29 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
@@ -149,6 +149,7 @@ public class SafetyCenterQsFragment extends Fragment {
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_center_qs, container, false);
root.setVisibility(View.GONE);
+ root.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
View closeButton = root.findViewById(R.id.close_button);
closeButton.setOnClickListener((v) -> requireActivity().finish());
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterSubpageFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterSubpageFragment.kt
index 5e45d2b3c..fdade2189 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterSubpageFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterSubpageFragment.kt
@@ -26,7 +26,7 @@ import com.android.permissioncontroller.Constants.EXTRA_SESSION_ID
import com.android.permissioncontroller.R
import com.android.permissioncontroller.safetycenter.ui.SafetyBrandChipPreference.Companion.closeSubpage
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterUiData
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.settingslib.widget.FooterPreference
/** A fragment that represents a generic subpage in Safety Center. */
@@ -72,7 +72,7 @@ class SafetyCenterSubpageFragment : SafetyCenterFragment() {
}
override fun renderSafetyCenterData(uiData: SafetyCenterUiData?) {
- Log.d(TAG, "renderSafetyCenterEntryGroup called with $uiData")
+ Log.v(TAG, "renderSafetyCenterEntryGroup called with $uiData")
val entryGroup = uiData?.getMatchingGroup(sourceGroupId)
if (entryGroup == null) {
Log.w(TAG, "$sourceGroupId doesn't match any of the existing SafetySourcesGroup IDs")
@@ -88,8 +88,7 @@ class SafetyCenterSubpageFragment : SafetyCenterFragment() {
private fun setupIllustration() {
val resName = "illustration_${SnakeCaseConverter.fromCamelCase(sourceGroupId)}"
val context = requireContext()
- val drawable =
- SafetyCenterResourcesContext(context).getDrawableByName(resName, context.theme)
+ val drawable = SafetyCenterResourcesApk(context).getDrawableByName(resName, context.theme)
if (drawable == null) {
Log.w(TAG, "$sourceGroupId doesn't have any matching illustration")
subpageIllustration.setVisible(false)
@@ -100,7 +99,7 @@ class SafetyCenterSubpageFragment : SafetyCenterFragment() {
private fun setupFooter() {
val resName = "${SnakeCaseConverter.fromCamelCase(sourceGroupId)}_footer"
- val footerText = SafetyCenterResourcesContext(requireContext()).getStringByName(resName)
+ val footerText = SafetyCenterResourcesApk(requireContext()).getStringByName(resName)
if (footerText.isEmpty()) {
Log.w(TAG, "$sourceGroupId doesn't have any matching footer")
subpageFooter.setVisible(false)
@@ -137,7 +136,7 @@ class SafetyCenterSubpageFragment : SafetyCenterFragment() {
}
private fun updateSafetyCenterEntries(entryGroup: SafetyCenterEntryGroup) {
- Log.d(TAG, "updateSafetyCenterEntries called with $entryGroup")
+ Log.v(TAG, "updateSafetyCenterEntries called with $entryGroup")
subpageEntryGroup.removeAll()
for (entry in entryGroup.entries) {
subpageEntryGroup.addPreference(
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
index 0b8706a38..3242ea84b 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyStatusPreference.java
@@ -27,6 +27,7 @@ import android.os.Looper;
import android.safetycenter.SafetyCenterStatus;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
@@ -49,6 +50,8 @@ import java.util.Objects;
@RequiresApi(TIRAMISU)
public class SafetyStatusPreference extends Preference implements ComparablePreference {
+ private static final String TAG = "SafetyStatusPreference";
+
@Nullable private StatusUiData mStatus;
@Nullable private SafetyCenterViewModel mViewModel;
@@ -72,6 +75,7 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ Log.d(TAG, String.format("onBindViewHolder called for status %s", mStatus));
if (mStatus == null) {
return;
@@ -335,6 +339,7 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
void setData(StatusUiData statusUiData) {
mStatus = statusUiData;
+ Log.d(TAG, String.format("setData called for status %s", mStatus));
safeNotifyChanged();
}
@@ -349,7 +354,14 @@ public class SafetyStatusPreference extends Preference implements ComparablePref
// Calling notifyChanged while recyclerview is scrolling or computing layout will result in an
// IllegalStateException. Post to handler to wait for UI to settle.
private void safeNotifyChanged() {
- new Handler(Looper.getMainLooper()).post(this::notifyChanged);
+ new Handler(Looper.getMainLooper())
+ .post(
+ () -> {
+ Log.d(
+ TAG,
+ String.format("Calling notifyChanged for status %s", mStatus));
+ notifyChanged();
+ });
}
@Override
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
index 39241ff9a..239f9a377 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
@@ -21,6 +21,7 @@ import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntryGroup
import android.safetycenter.SafetyCenterEntryOrGroup
import android.safetycenter.SafetyCenterIssue
+import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK
import androidx.annotation.RequiresApi
import com.android.safetycenter.internaldata.SafetyCenterBundles.ISSUES_TO_GROUPS_BUNDLE_KEY
@@ -51,7 +52,7 @@ data class SafetyCenterUiData(
*/
@RequiresApi(UPSIDE_DOWN_CAKE)
fun getMatchingDismissedIssues(groupId: String): List<SafetyCenterIssue> =
- selectMatchingIssuesForGroup(groupId, safetyCenterData.dismissedIssues)
+ selectMatchingIssuesForGroup(groupId, safetyCenterData.visibleDismissedIssues())
@RequiresApi(UPSIDE_DOWN_CAKE)
private fun selectMatchingIssuesForGroup(
@@ -68,4 +69,9 @@ data class SafetyCenterUiData(
if (mappingExists) matchesInMapping else matchesByDefault
}
}
+
+ /** Returns the [SafetyCenterData.getDismissedIssues] that are meant to be visible in the UI. */
+ @RequiresApi(UPSIDE_DOWN_CAKE)
+ fun SafetyCenterData.visibleDismissedIssues() =
+ dismissedIssues.filter { it.severityLevel > ISSUE_SEVERITY_LEVEL_OK }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/LazyProperties.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/LazyProperties.kt
new file mode 100644
index 000000000..542ab1e03
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/LazyProperties.kt
@@ -0,0 +1,12 @@
+package com.android.permissioncontroller.safetycenter.ui.view
+
+import android.view.View
+
+/** Returns a lazy property wrapping a view with a given ID. */
+fun <T> View.lazyView(childViewId: Int): Lazy<T> = lazyView { findViewById(childViewId) }
+
+/** Returns a lazy property wrapping a view produced by the given function. */
+fun <T> lazyView(viewProducer: () -> T): Lazy<T> =
+ // Lazy by default uses synchronization to ensure a variable is only initialized once. This
+ // is unnecessary and expensive for view properties, so we don't use synchronization here.
+ lazy(LazyThreadSafetyMode.NONE) { viewProducer() }
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/MoreIssuesHeaderView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/MoreIssuesHeaderView.kt
index 264aa488e..00cfd141a 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/MoreIssuesHeaderView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/MoreIssuesHeaderView.kt
@@ -43,13 +43,13 @@ constructor(
}
private val moreIssuesCardAnimator = MoreIssuesCardAnimator()
- private val statusIconView: ImageView by lazy { findViewById(R.id.status_icon) }
- private val titleView: TextView by lazy { findViewById(R.id.title) }
- private val expandCollapseLayout: View by lazy { findViewById(android.R.id.widget_frame) }
- private val counterView: TextView by lazy {
+ private val statusIconView: ImageView by lazyView(R.id.status_icon)
+ private val titleView: TextView by lazyView(R.id.title)
+ private val expandCollapseLayout: View by lazyView(android.R.id.widget_frame)
+ private val counterView: TextView by lazyView {
expandCollapseLayout.findViewById(R.id.widget_title)
}
- private val expandCollapseIcon: ImageView by lazy {
+ private val expandCollapseIcon: ImageView by lazyView {
expandCollapseLayout.findViewById(R.id.widget_icon)
}
private var cornerAnimator: ValueAnimator? = null
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryCommonViewsManager.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryCommonViewsManager.kt
index 4be327285..34565421a 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryCommonViewsManager.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryCommonViewsManager.kt
@@ -29,11 +29,11 @@ import com.android.permissioncontroller.safetycenter.ui.SeverityIconPicker
internal class SafetyEntryCommonViewsManager(rootEntryView: ViewGroup?) {
- val titleView: TextView? by lazy { rootEntryView?.findViewById(R.id.title) }
- val summaryView: TextView? by lazy { rootEntryView?.findViewById(R.id.summary) }
- private val iconView: ImageView? by lazy { rootEntryView?.findViewById(R.id.icon) }
- private val iconFrame: View? by lazy { rootEntryView?.findViewById(R.id.icon_frame) }
- private val emptySpace: View? by lazy { rootEntryView?.findViewById(R.id.empty_space) }
+ val titleView: TextView? by lazyView { rootEntryView?.findViewById(R.id.title) }
+ val summaryView: TextView? by lazyView { rootEntryView?.findViewById(R.id.summary) }
+ private val iconView: ImageView? by lazyView { rootEntryView?.findViewById(R.id.icon) }
+ private val iconFrame: View? by lazyView { rootEntryView?.findViewById(R.id.icon_frame) }
+ private val emptySpace: View? by lazyView { rootEntryView?.findViewById(R.id.empty_space) }
fun showDetails(
id: String,
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
index 318ade5cb..b00b7f765 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryGroupView.kt
@@ -51,7 +51,6 @@ constructor(
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
private companion object {
- val TAG = SafetyEntryGroupView::class.java.simpleName
const val EXPAND_COLLAPSE_ANIMATION_DURATION_MS = 183L
}
@@ -59,20 +58,20 @@ constructor(
inflate(context, R.layout.safety_center_group, this)
}
- private val groupHeaderView: LinearLayout? by lazy { findViewById(R.id.group_header) }
+ private val groupHeaderView: LinearLayout? by lazyView(R.id.group_header)
- private val expandedHeaderView: ViewGroup? by lazy { findViewById(R.id.expanded_header) }
- private val expandedTitleView: TextView? by lazy {
+ private val expandedHeaderView: ViewGroup? by lazyView(R.id.expanded_header)
+ private val expandedTitleView: TextView? by lazyView {
expandedHeaderView?.findViewById(R.id.title)
}
- private val collapsedHeaderView: ViewGroup? by lazy { findViewById(R.id.collapsed_header) }
- private val commonEntryView: SafetyEntryCommonViewsManager? by lazy {
+ private val collapsedHeaderView: ViewGroup? by lazyView(R.id.collapsed_header)
+ private val commonEntryView: SafetyEntryCommonViewsManager? by lazyView {
SafetyEntryCommonViewsManager(collapsedHeaderView)
}
- private val chevronIconView: ImageView? by lazy { findViewById(R.id.chevron_icon) }
- private val entriesContainerView: LinearLayout? by lazy { findViewById(R.id.entries_container) }
+ private val chevronIconView: ImageView? by lazyView(R.id.chevron_icon)
+ private val entriesContainerView: LinearLayout? by lazyView(R.id.entries_container)
private var isExpanded: Boolean? = null
@@ -107,8 +106,15 @@ constructor(
val params = layoutParams as MarginLayoutParams
if (params.topMargin != topMargin) {
params.topMargin = topMargin
- layoutParams = params
}
+
+ if (isLastCard) {
+ params.bottomMargin = context.resources.getDimensionPixelSize(R.dimen.sc_spacing_large)
+ } else {
+ params.bottomMargin = 0
+ }
+
+ layoutParams = params
}
private fun showGroupDetails(group: SafetyCenterEntryGroup) {
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryView.kt
index ff7233686..7d7214ab0 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/SafetyEntryView.kt
@@ -52,10 +52,10 @@ constructor(
inflate(context, R.layout.view_entry, this)
}
- private val commonEntryView: SafetyEntryCommonViewsManager? by lazy {
+ private val commonEntryView: SafetyEntryCommonViewsManager? by lazyView {
SafetyEntryCommonViewsManager(this)
}
- private val widgetFrame: ViewGroup? by lazy { findViewById(R.id.widget_frame) }
+ private val widgetFrame: ViewGroup? by lazyView(R.id.widget_frame)
fun showEntry(
entry: SafetyCenterEntry,
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt
index 013f32c85..6a415c563 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/view/StatusCardView.kt
@@ -42,14 +42,12 @@ constructor(
inflate(context, R.layout.view_status_card, this)
}
- val statusImageView: ImageView by lazy { findViewById(R.id.status_image) }
- val titleAndSummaryContainerView: LinearLayout by lazy {
- findViewById(R.id.status_title_and_summary)
- }
- val titleView: TextView by lazy { findViewById(R.id.status_title) }
- val summaryView: TextView by lazy { findViewById(R.id.status_summary) }
- val reviewSettingsButton: MaterialButton by lazy { findViewById(R.id.review_settings_button) }
- val rescanButton: MaterialButton by lazy { findViewById(R.id.rescan_button) }
+ val statusImageView: ImageView by lazyView(R.id.status_image)
+ val titleAndSummaryContainerView: LinearLayout by lazyView(R.id.status_title_and_summary)
+ val titleView: TextView by lazyView(R.id.status_title)
+ val summaryView: TextView by lazyView(R.id.status_summary)
+ val reviewSettingsButton: MaterialButton by lazyView(R.id.review_settings_button)
+ val rescanButton: MaterialButton by lazyView(R.id.rescan_button)
fun showButtons(statusUiData: StatusUiData) {
rescanButton.isEnabled = !statusUiData.isRefreshInProgress
diff --git a/PermissionController/src/com/android/permissioncontroller/safetylabel/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/safetylabel/TEST_MAPPING
index b6e659353..1503c5e57 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetylabel/TEST_MAPPING
+++ b/PermissionController/src/com/android/permissioncontroller/safetylabel/TEST_MAPPING
@@ -11,17 +11,40 @@
],
"presubmit-large": [
{
- "name": "CtsPermission3TestCases",
+ "name": "CtsPermissionUiTestCases",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
],
"mainline-presubmit": [
{
- "name": "CtsPermission3TestCases[com.google.android.permission.apex]"
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "PermissionControllerMockingTests",
+ "options": [
+ {
+ "include-filter": "com.android.permissioncontroller.tests.mocking.safetylabel"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermissionUiTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]"
}
]
} \ No newline at end of file
diff --git a/PermissionController/tests/inprocess/Android.bp b/PermissionController/tests/inprocess/Android.bp
index 78c767f1d..7d55ff9cc 100644
--- a/PermissionController/tests/inprocess/Android.bp
+++ b/PermissionController/tests/inprocess/Android.bp
@@ -33,10 +33,7 @@ android_test {
target_sdk_version: "30",
min_sdk_version: "30",
- srcs: [
- "src/**/*.kt",
- "src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java",
- ],
+ srcs: ["src/**/*.kt"],
libs: [
"android.test.base",
diff --git a/PermissionController/tests/inprocess/AndroidTest.xml b/PermissionController/tests/inprocess/AndroidTest.xml
index 8971a7270..e09fe556b 100644
--- a/PermissionController/tests/inprocess/AndroidTest.xml
+++ b/PermissionController/tests/inprocess/AndroidTest.xml
@@ -30,14 +30,14 @@
<!-- Create place to store apks -->
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/permissioncontroller/tests/inprocess" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/permissioncontroller/"/>
+ <option name="run-command" value="mkdir -p /data/local/tmp/pc-inprocess" />
+ <option name="teardown-command" value="rm -fr /data/local/tmp/pc-inprocess"/>
</target_preparer>
<!-- Load additional APKs onto device -->
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="push-file" key="AppThatUsesCameraPermission.apk"
- value="/data/local/tmp/permissioncontroller/tests/inprocess/AppThatUsesCameraPermission.apk" />
+ value="/data/local/tmp/pc-inprocess/AppThatUsesCameraPermission.apk" />
</target_preparer>
<!-- Uninstall test-apps -->
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java
deleted file mode 100644
index b4b18dbbe..000000000
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/compat/LinkMovementMethodCompatTest.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2023 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.compat;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.SystemClock;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.method.MovementMethod;
-import android.text.style.ClickableSpan;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.rule.ActivityTestRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-/**
- * Test for {@link LinkMovementMethodCompat} without using Mockito, which is unavailable for
- * in-process tests.
- *
- * @see android.text.method.cts.LinkMovementMethodTest
- */
-public class LinkMovementMethodCompatTest {
- private static final String CONTENT = "clickable\nunclickable\nclickable";
-
- private Activity mActivity;
- private LinkMovementMethodCompat mMethod;
- private TextView mView;
- private Spannable mSpannable;
- private MockClickableSpan mClickable0;
- private MockClickableSpan mClickable1;
-
- @Rule
- public ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
-
- @Before
- public void setup() throws Throwable {
- mActivity = mActivityRule.getActivity();
- mMethod = new LinkMovementMethodCompat();
-
- // Set the content view with a text view which contains 3 lines,
- mActivityRule.runOnUiThread(() -> mView = new TextViewNoIme(mActivity));
- mView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
- mView.setText(CONTENT, TextView.BufferType.SPANNABLE);
-
- mActivityRule.runOnUiThread(() -> mActivity.setContentView(mView));
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-
- mSpannable = (Spannable) mView.getText();
- // make first line clickable
- mClickable0 = markClickable(0, CONTENT.indexOf('\n'));
- // make last line clickable
- mClickable1 = markClickable(CONTENT.lastIndexOf('\n'), CONTENT.length());
- }
-
- @Test
- public void testConstructor() {
- new LinkMovementMethodCompat();
- }
-
- @Test
- public void testGetInstance() {
- MovementMethod method0 = LinkMovementMethodCompat.getInstance();
- assertTrue(method0 instanceof LinkMovementMethodCompat);
-
- MovementMethod method1 = LinkMovementMethodCompat.getInstance();
- assertNotNull(method1);
- assertSame(method0, method1);
- }
-
- @UiThreadTest
- @Test
- public void testOnTouchEvent() {
- assertSelection(mSpannable, -1);
-
- // press on first line (Clickable)
- assertTrue(pressOnLine(0));
- assertSelectClickableLeftToRight(mSpannable, mClickable0);
-
- // release on first line
- mClickable0.clearClickCount();
- assertTrue(releaseOnLine(0));
- mClickable0.assertClickCount(1);
-
- // press on second line (unclickable)
- assertSelectClickableLeftToRight(mSpannable, mClickable0);
- // just clear selection
- pressOnLine(1);
- assertSelection(mSpannable, -1);
-
- // press on last line (Clickable)
- assertTrue(pressOnLine(2));
- assertSelectClickableLeftToRight(mSpannable, mClickable1);
-
- // release on last line
- mClickable1.clearClickCount();
- assertTrue(releaseOnLine(2));
- mClickable1.assertClickCount(1);
-
- // release on second line (unclickable)
- assertSelectClickableLeftToRight(mSpannable, mClickable1);
- // just clear selection
- releaseOnLine(1);
- assertSelection(mSpannable, -1);
- }
-
- @UiThreadTest
- @Test
- public void testOnTouchEvent_outsideLineBounds() {
- assertSelection(mSpannable, -1);
-
- // press on first line (clickable)
- assertTrue(pressOnLine(0));
- assertSelectClickableLeftToRight(mSpannable, mClickable0);
-
- // release above first line
- mClickable0.clearClickCount();
- float x = (mView.getLayout().getLineLeft(0) + mView.getLayout().getLineRight(0)) / 2f;
- float y = -1f;
- assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
- mClickable0.assertClickCount(0);
-
- // press on first line (clickable)
- assertTrue(pressOnLine(0));
- assertSelectClickableLeftToRight(mSpannable, mClickable0);
-
- // release to left of first line
- mClickable0.clearClickCount();
- x = mView.getLayout().getLineLeft(0) - 1f;
- y = (mView.getLayout().getLineTop(0) + mView.getLayout().getLineBottom(0)) / 2f;
- assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
- mClickable0.assertClickCount(0);
-
- // press on first line (clickable)
- assertTrue(pressOnLine(0));
- assertSelectClickableLeftToRight(mSpannable, mClickable0);
-
- // release to right of first line
- mClickable0.clearClickCount();
- x = mView.getLayout().getLineRight(0) + 1f;
- y = (mView.getLayout().getLineTop(0) + mView.getLayout().getLineBottom(0)) / 2f;
- assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
- mClickable0.assertClickCount(0);
-
- // press on last line (clickable)
- assertTrue(pressOnLine(2));
- assertSelectClickableLeftToRight(mSpannable, mClickable1);
-
- // release below last line
- mClickable1.clearClickCount();
- x = (mView.getLayout().getLineLeft(0) + mView.getLayout().getLineRight(0)) / 2f;
- y = mView.getLayout().getHeight() + 1f;
- assertFalse(performMotionAtPoint(x, y, MotionEvent.ACTION_UP));
- mClickable1.assertClickCount(0);
- }
-
- private MockClickableSpan markClickable(final int start, final int end) throws Throwable {
- final MockClickableSpan clickableSpan = new MockClickableSpan();
- mActivityRule.runOnUiThread(() -> mSpannable.setSpan(clickableSpan, start, end,
- Spanned.SPAN_MARK_MARK));
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- return clickableSpan;
- }
- private boolean performMotionAtPoint(float x, float y, int action) {
- long now = SystemClock.uptimeMillis();
- return mMethod.onTouchEvent(mView, mSpannable,
- MotionEvent.obtain(now, now, action, x, y, 0));
- }
-
- private boolean performMotionOnLine(int line, int action) {
- float x = (mView.getLayout().getLineLeft(line) + mView.getLayout().getLineRight(line)) / 2f;
- float y = (mView.getLayout().getLineTop(line) + mView.getLayout().getLineBottom(line)) / 2f;
- return performMotionAtPoint(x, y, action);
- }
-
- private boolean pressOnLine(int line) {
- return performMotionOnLine(line, MotionEvent.ACTION_DOWN);
- }
-
- private boolean releaseOnLine(int line) {
- return performMotionOnLine(line, MotionEvent.ACTION_UP);
- }
-
- private void assertSelection(Spannable spannable, int start, int end) {
- assertEquals(start, Selection.getSelectionStart(spannable));
- assertEquals(end, Selection.getSelectionEnd(spannable));
- }
-
- private void assertSelection(Spannable spannable, int position) {
- assertSelection(spannable, position, position);
- }
-
- private void assertSelectClickableLeftToRight(Spannable spannable,
- ClickableSpan clickableSpan) {
- assertSelection(spannable, spannable.getSpanStart(clickableSpan),
- spannable.getSpanEnd(clickableSpan));
- }
-
- public static class TextViewNoIme extends TextView {
- public TextViewNoIme(@NonNull Context context) {
- super(context);
- }
-
- @Override
- public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- return null;
- }
- }
-
- public static class MockClickableSpan extends ClickableSpan {
- private int mClickCount = 0;
-
- @Override
- public void onClick(@NonNull View widget) {
- ++mClickCount;
- }
-
- public void assertClickCount(int expectedClickCount) {
- assertEquals(expectedClickCount, mClickCount);
- }
-
- public void clearClickCount() {
- mClickCount = 0;
- }
- }
-}
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
index 24ea039a1..f7f6dcbd4 100644
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
+++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/data/AttributionLabelLiveDataTest.kt
@@ -29,7 +29,7 @@ import org.junit.Before
import org.junit.Test
private const val APK =
- "/data/local/tmp/permissioncontroller/tests/inprocess/AppThatUsesCameraPermission.apk"
+ "/data/local/tmp/pc-inprocess/AppThatUsesCameraPermission.apk"
private const val PKG = "com.android.permissioncontroller.tests.appthatrequestpermission"
class AttributionLabelLiveDataTest {
diff --git a/PermissionController/tests/mocking/Android.bp b/PermissionController/tests/mocking/Android.bp
index 0c7c3e675..863c7baab 100644
--- a/PermissionController/tests/mocking/Android.bp
+++ b/PermissionController/tests/mocking/Android.bp
@@ -53,6 +53,10 @@ android_test {
"iconloader_sc_mainline_prod",
"com.google.android.material_material",
"androidx.transition_transition",
+ "androidx.compose.foundation_foundation",
+ "androidx.compose.runtime_runtime",
+ "androidx.compose.runtime_runtime-livedata",
+ "androidx.compose.ui_ui",
"androidx-constraintlayout_constraintlayout",
"androidx.core_core",
"androidx.media_media",
@@ -67,6 +71,7 @@ android_test {
"androidx.leanback_leanback-preference",
"androidx.lifecycle_lifecycle-extensions",
"androidx.lifecycle_lifecycle-common-java8",
+ "androidx.wear.compose_compose-material",
"kotlin-stdlib",
"kotlinx-coroutines-android",
"androidx.navigation_navigation-common-ktx",
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
index d576f2924..694986312 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/service/RuntimePermissionsUpgradeControllerTest.kt
@@ -24,6 +24,7 @@ import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.Manifest.permission.READ_MEDIA_AUDIO
import android.Manifest.permission.READ_MEDIA_IMAGES
import android.Manifest.permission.READ_MEDIA_VIDEO
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
import android.Manifest.permission.SEND_SMS
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.ActivityManager
@@ -60,6 +61,7 @@ import org.junit.Assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.AdditionalMatchers
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
@@ -547,6 +549,71 @@ class RuntimePermissionsUpgradeControllerTest {
verifyGranted(TEST_PKG_NAME, READ_MEDIA_IMAGES)
}
+ @Test
+ fun userSelectedGrantedIfReadMediaVisualGrantedWhenVersionIs10() {
+ Assume.assumeTrue(SdkLevel.isAtLeastU())
+ whenever(packageManager.isDeviceUpgrading).thenReturn(true)
+ setInitialDatabaseVersion(10)
+ setPackages(
+ Package(TEST_PKG_NAME,
+ Permission(READ_MEDIA_VIDEO, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_IMAGES, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
+ targetSdkVersion = 33
+ )
+ )
+
+ upgradeIfNeeded()
+
+ verifyGranted(TEST_PKG_NAME, READ_MEDIA_VISUAL_USER_SELECTED)
+ }
+
+ @Test
+ fun userSelectedNotGrantedIfDeviceNotUpgradingWhenVersionIs10() {
+ Assume.assumeTrue(SdkLevel.isAtLeastU())
+ whenever(packageManager.isDeviceUpgrading).thenReturn(false)
+ setInitialDatabaseVersion(10)
+ setPackages(
+ Package(TEST_PKG_NAME,
+ Permission(READ_MEDIA_VIDEO, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_IMAGES, isGranted = true, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
+ targetSdkVersion = 33
+ )
+ )
+
+ upgradeIfNeeded()
+
+ verifyNotGranted(TEST_PKG_NAME, READ_MEDIA_VISUAL_USER_SELECTED)
+ }
+
+ @Test
+ fun userSelectedNotGrantedIfReadMediaVisualNotGrantedWhenVersionIs10() {
+ Assume.assumeTrue(SdkLevel.isAtLeastU())
+ whenever(packageManager.isDeviceUpgrading).thenReturn(false)
+ setInitialDatabaseVersion(10)
+ setPackages(
+ Package(TEST_PKG_NAME,
+ Permission(READ_MEDIA_VIDEO, isGranted = false, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_IMAGES, isGranted = false, flags = FLAG_PERMISSION_USER_SET),
+ Permission(READ_MEDIA_VISUAL_USER_SELECTED, isGranted = false),
+ targetSdkVersion = 33
+ )
+ )
+
+ upgradeIfNeeded()
+
+ verifyNotGranted(TEST_PKG_NAME, READ_MEDIA_VISUAL_USER_SELECTED)
+ }
+
+ @Test
+ fun ensureDatabaseResetToLatestIfAboveLatest() {
+ setInitialDatabaseVersion(Int.MAX_VALUE)
+ upgradeIfNeeded()
+ verify(permissionManager).runtimePermissionsVersion =
+ AdditionalMatchers.not(eq(Int.MAX_VALUE))
+ }
+
@After
fun resetSystem() {
// Send low memory notifications for all data repositories which will clear cached data
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
index 34ea6fcf0..ca0392716 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
@@ -22,6 +22,9 @@ import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntryGroup
import android.safetycenter.SafetyCenterEntryOrGroup
import android.safetycenter.SafetyCenterIssue
+import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING
+import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_OK
+import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATION
import android.safetycenter.SafetyCenterStatus
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -209,6 +212,44 @@ class SafetyCenterUiDataTest {
assertThat(result).isEmpty()
}
+ @Test
+ fun getMatchingDismissedIssues_doesntReturnGreenIssues() {
+ val greenDismissedIssue =
+ createSafetyCenterIssue(
+ "id1",
+ MATCHING_GROUP_ID,
+ severityLevel = ISSUE_SEVERITY_LEVEL_OK
+ )
+ val yellowDismissedIssue =
+ createSafetyCenterIssue(
+ "id2",
+ MATCHING_GROUP_ID,
+ severityLevel = ISSUE_SEVERITY_LEVEL_RECOMMENDATION
+ )
+ val redDismissedIssue =
+ createSafetyCenterIssue(
+ "id3",
+ MATCHING_GROUP_ID,
+ severityLevel = ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING
+ )
+ val nonMatchingDismissedIssue = createSafetyCenterIssue("id4", NON_MATCHING_GROUP_ID)
+ val safetyCenterData =
+ createSafetyCenterData(
+ dismissedIssues =
+ listOf(
+ redDismissedIssue,
+ yellowDismissedIssue,
+ greenDismissedIssue,
+ nonMatchingDismissedIssue
+ ),
+ )
+
+ val result =
+ SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+
+ assertThat(result).containsExactly(redDismissedIssue, yellowDismissedIssue).inOrder()
+ }
+
private companion object {
const val MATCHING_GROUP_ID = "matching_group_id"
const val NON_MATCHING_GROUP_ID = "non_matching_group_id"
@@ -238,8 +279,13 @@ class SafetyCenterUiDataTest {
fun createSafetyCenterEntryGroup(groupId: String) =
SafetyCenterEntryGroup.Builder(groupId, "group title").build()
- fun createSafetyCenterIssue(issueId: String, groupId: String) =
+ fun createSafetyCenterIssue(
+ issueId: String,
+ groupId: String,
+ severityLevel: Int = ISSUE_SEVERITY_LEVEL_RECOMMENDATION
+ ) =
SafetyCenterIssue.Builder(issueId, "issue title", "issue summary")
+ .setSeverityLevel(severityLevel)
.setGroupId(groupId)
.build()
diff --git a/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt b/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
index 4963a4683..8d82967e2 100644
--- a/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
+++ b/PermissionController/tests/outofprocess/src/com/android/permissioncontroller/tests/outofprocess/DumpTest.kt
@@ -20,11 +20,14 @@ import android.os.ParcelFileDescriptor.AutoCloseInputStream
import android.os.UserHandle.myUserId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
+import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.PermissionControllerProto.PermissionControllerDumpProto
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.InvalidProtocolBufferException
import org.junit.Assert.fail
+import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.nio.charset.StandardCharsets.UTF_8
@@ -48,6 +51,12 @@ class DumpTest {
}
}
+ @Before
+ fun setUp() {
+ // We no longer dump auto revoke data since T.
+ assumeFalse(SdkLevel.isAtLeastT())
+ }
+
@Test
fun autoRevokeDumpHasCurrentUser() {
val dump = getDump()
diff --git a/PermissionController/tests/permissionui/Android.bp b/PermissionController/tests/permissionui/Android.bp
index 704307c1f..9a898d88b 100644
--- a/PermissionController/tests/permissionui/Android.bp
+++ b/PermissionController/tests/permissionui/Android.bp
@@ -60,6 +60,8 @@ android_test {
":CtsAppThatRequestsLocationPermission29",
":PermissionUiUseStoragePermissionApp",
":PermissionUiUseCameraPermissionApp",
+ ":PermissionUiUseHealthConnectPermissionApp",
+ ":PermissionUiInvalidUseHealthConnectPermissionApp",
":PermissionUiDefineAdditionalPermissionApp",
":PermissionUiUseAdditionalPermissionApp",
":PermissionUiUseTwoAdditionalPermissionsApp",
diff --git a/PermissionController/tests/permissionui/AndroidTest.xml b/PermissionController/tests/permissionui/AndroidTest.xml
index 62fc6ed3f..85ccf61ce 100644
--- a/PermissionController/tests/permissionui/AndroidTest.xml
+++ b/PermissionController/tests/permissionui/AndroidTest.xml
@@ -31,24 +31,28 @@
<!-- Create place to store apks -->
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="mkdir -p /data/local/tmp/permissioncontroller/tests/permissionui" />
- <option name="teardown-command" value="rm -rf /data/local/tmp/permissioncontroller/"/>
+ <option name="run-command" value="mkdir -p /data/local/tmp/pc-permissionui" />
+ <option name="teardown-command" value="rm -fr /data/local/tmp/pc-permissionui"/>
</target_preparer>
<!-- Load additional APKs onto device -->
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="push-file" key="CtsAppThatRequestsLocationPermission29.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk" />
+ value="/data/local/tmp/pc-permissionui/AppThatRequestsLocation.apk" />
<option name="push-file" key="PermissionUiUseStoragePermissionApp.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/PermissionUiUseStoragePermissionApp.apk" />
+ value="/data/local/tmp/pc-permissionui/PermissionUiUseStoragePermissionApp.apk" />
<option name="push-file" key="PermissionUiUseCameraPermissionApp.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/PermissionUiUseCameraPermissionApp.apk" />
+ value="/data/local/tmp/pc-permissionui/PermissionUiUseCameraPermissionApp.apk" />
+ <option name="push-file" key="PermissionUiUseHealthConnectPermissionApp.apk"
+ value="/data/local/tmp/pc-permissionui/PermissionUiUseHealthConnectPermissionApp.apk" />
+ <option name="push-file" key="PermissionUiInvalidUseHealthConnectPermissionApp.apk"
+ value="/data/local/tmp/pc-permissionui/PermissionUiInvalidUseHealthConnectPermissionApp.apk" />
<option name="push-file" key="PermissionUiDefineAdditionalPermissionApp.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/PermissionUiDefineAdditionalPermissionApp.apk" />
+ value="/data/local/tmp/pc-permissionui/PermissionUiDefineAdditionalPermissionApp.apk" />
<option name="push-file" key="PermissionUiUseAdditionalPermissionApp.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/PermissionUiUseAdditionalPermissionApp.apk" />
+ value="/data/local/tmp/pc-permissionui/PermissionUiUseAdditionalPermissionApp.apk" />
<option name="push-file" key="PermissionUiUseTwoAdditionalPermissionsApp.apk"
- value="/data/local/tmp/permissioncontroller/tests/permissionui/PermissionUiUseTwoAdditionalPermissionsApp.apk" />
+ value="/data/local/tmp/pc-permissionui/PermissionUiUseTwoAdditionalPermissionsApp.apk" />
</target_preparer>
<!-- Uninstall test-apps -->
diff --git a/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/Android.bp b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/Android.bp
new file mode 100644
index 000000000..c366f9a0c
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_modules_Permission_PermissionController_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "packages_modules_Permission_PermissionController_license",
+ ],
+}
+
+android_test_helper_app {
+ name: "PermissionUiInvalidUseHealthConnectPermissionApp",
+
+ srcs: ["src/**/*.kt"],
+
+ sdk_version: "34",
+}
diff --git a/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/AndroidManifest.xml b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/AndroidManifest.xml
new file mode 100644
index 000000000..c5e0f4906
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.permissioncontroller.tests.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.health.READ_FLOORS_CLIMBED" />
+ <uses-permission android:name="android.permission.health.READ_STEPS" />
+
+ <application android:label="HealthConnectRequestApp" />
+</manifest>
+
diff --git a/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
new file mode 100644
index 000000000..98089208a
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiInvalidUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.tests.appthatrequestpermission
+
+import android.app.Activity
+
+class DummyActivity : Activity()
diff --git a/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/Android.bp b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/Android.bp
new file mode 100644
index 000000000..10788a116
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "packages_modules_Permission_PermissionController_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "packages_modules_Permission_PermissionController_license",
+ ],
+}
+
+android_test_helper_app {
+ name: "PermissionUiUseHealthConnectPermissionApp",
+
+ srcs: ["src/**/*.kt"],
+
+ sdk_version: "34",
+}
diff --git a/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/AndroidManifest.xml b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/AndroidManifest.xml
new file mode 100644
index 000000000..d5903a543
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.permissioncontroller.tests.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.health.READ_FLOORS_CLIMBED" />
+ <uses-permission android:name="android.permission.health.READ_STEPS" />
+
+ <application android:label="HealthConnectRequestApp">
+ <activity android:name=".DummyActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
+ <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
+
diff --git a/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
new file mode 100644
index 000000000..98089208a
--- /dev/null
+++ b/PermissionController/tests/permissionui/PermissionUiUseHealthConnectPermissionApp/src/com/android/permissioncontroller/tests/appthatrequestpermission/DummyActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 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.tests.appthatrequestpermission
+
+import android.app.Activity
+
+class DummyActivity : Activity()
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
index 6f143d2db..2f9b3c76a 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/PermissionHub2Test.kt
@@ -25,15 +25,10 @@ import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
import android.os.Process.myUserHandle
-import android.provider.DeviceConfig
-import android.provider.DeviceConfig.NAMESPACE_PRIVACY
import androidx.test.platform.app.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil.eventually
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.google.common.truth.Truth.assertThat
-import org.junit.AfterClass
-import org.junit.BeforeClass
/**
* Super class with utilities for testing permission hub 2 code
@@ -44,36 +39,6 @@ open class PermissionHub2Test {
private val instrumentation = InstrumentationRegistry.getInstrumentation()
protected val context = instrumentation.targetContext
- companion object {
- private const val PROPERTY_PERMISSIONS_HUB_2_ENABLED = "permissions_hub_2_enabled"
-
- private var wasPermissionHubEnabled = false
-
- @JvmStatic
- @BeforeClass
- fun enablePermissionHub2() {
-
- runWithShellPermissionIdentity {
- wasPermissionHubEnabled = DeviceConfig.getBoolean(NAMESPACE_PRIVACY,
- PROPERTY_PERMISSIONS_HUB_2_ENABLED, false)
- }
-
- if (!wasPermissionHubEnabled) {
- runShellCommand(
- "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED true")
- }
- }
-
- @JvmStatic
- @AfterClass
- fun disablePermissionHub2() {
- if (!wasPermissionHubEnabled) {
- runShellCommand(
- "device_config put privacy $PROPERTY_PERMISSIONS_HUB_2_ENABLED false")
- }
- }
- }
-
/**
* Make {@value #APP} access the camera
*/
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
index d5f574327..d87dfacb0 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AllAppPermissionsFragmentTest.kt
@@ -46,13 +46,13 @@ private const val ALL_PERMISSIONS = "All permissions"
@RunWith(AndroidJUnit4::class)
class AllAppPermissionsFragmentTest : BasePermissionUiTest() {
private val ONE_PERMISSION_DEFINER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
+ "/data/local/tmp/pc-permissionui/" +
"PermissionUiDefineAdditionalPermissionApp.apk"
private val PERMISSION_USER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
+ "/data/local/tmp/pc-permissionui/" +
"PermissionUiUseAdditionalPermissionApp.apk"
private val TWO_PERMISSION_USER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
+ "/data/local/tmp/pc-permissionui/" +
"PermissionUiUseTwoAdditionalPermissionsApp.apk"
private val DEFINER_PKG = "com.android.permissioncontroller.tests.appthatdefinespermission"
private val USER_PKG = "com.android.permissioncontroller.tests.appthatrequestpermission"
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
index 7b058d004..15fc20622 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/AppPermissionFragmentTest.kt
@@ -31,6 +31,7 @@ import org.junit.After
import org.junit.Assert.assertNull
import org.junit.Assume.assumeFalse
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@@ -85,6 +86,7 @@ class AppPermissionFragmentTest : BasePermissionUiTest() {
}
@Test
+ @Ignore("b/301001789")
fun activityIsClosedWhenUserIsUninstalled() {
uninstallApp(USER_PKG)
eventually {
@@ -93,6 +95,7 @@ class AppPermissionFragmentTest : BasePermissionUiTest() {
}
@Test
+ @Ignore("b/301001789")
fun activityIsClosedWhenDefinerIsUninstalled() {
uninstallApp(DEFINER_PKG)
eventually {
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
index 988cbca73..b31458978 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/CustomPermissionAppsFragmentTest.kt
@@ -36,11 +36,11 @@ private const val PERMISSION_APPS_DESCRIPTION = "Apps with this permission"
*/
@RunWith(AndroidJUnit4::class)
class CustomPermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/data/local/tmp/pc-permissionui" +
"/PermissionUiUseAdditionalPermissionApp.apk",
"com.android.permissioncontroller.tests.appthatrequestpermission",
"com.android.permissioncontroller.tests.A",
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/data/local/tmp/pc-permissionui" +
"/PermissionUiDefineAdditionalPermissionApp.apk",
"com.android.permissioncontroller.tests.appthatdefinespermission"
) {
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt
new file mode 100644
index 000000000..0611ec3c4
--- /dev/null
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAllAppPermissionFragmentTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 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.permissionui.ui
+
+import android.content.Intent
+import android.os.Build
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
+import com.android.permissioncontroller.permissionui.wakeUpScreen
+import org.junit.After
+import org.junit.Assert.assertNull
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Simple tests for {@link AllAppPermissionsFragment} for Health Connect behaviors
+ * Currently, does NOT run on TV.
+ * TODO(b/178576541): Adapt and run on TV.
+ * Run with:
+ * atest HealthConnectAllAppPermissionFragmentTest
+ */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+class HealthConnectAllAppPermissionFragmentTest : BasePermissionUiTest() {
+ @Before
+ fun assumeNotTelevision() = assumeFalse(isTelevision)
+
+ @Before
+ fun wakeScreenUp() {
+ wakeUpScreen()
+ }
+
+ @After
+ fun uninstallTestApp() {
+ uninstallTestApps()
+ }
+ @Test
+ fun usedHealthConnectPermissionsAreListed() {
+ installTestAppThatUsesHealthConnectPermission()
+
+ startManageAppPermissionsActivity()
+
+ eventually {
+ waitFindObject(By.text(HEALTH_CONNECT_LABEL))
+ waitFindObject(By.text(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL))
+ waitFindObject(By.text(HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL))
+ }
+ }
+
+ @Test
+ fun invalidUngrantedUsedHealthConnectPermissionsAreNotListed() {
+ installInvalidTestAppThatUsesHealthConnectPermission()
+
+ startManageAppPermissionsActivity()
+
+ eventually {
+ assertNull(waitFindObjectOrNull(By.text(HEALTH_CONNECT_LABEL), TIMEOUT_SHORT))
+ assertNull(waitFindObjectOrNull(
+ By.text(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL), TIMEOUT_SHORT))
+ assertNull(waitFindObjectOrNull(
+ By.text(HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL), TIMEOUT_SHORT))
+ }
+ }
+
+ @Test
+ fun invalidGrantedUsedHealthConnectPermissionsAreListed() {
+ installInvalidTestAppThatUsesHealthConnectPermission()
+ grantTestAppPermission(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED)
+
+ startManageAppPermissionsActivity()
+
+ // Ensure that Health Connect permission group permissions are present if a single one is
+ // already granted, regardless of whether the intent filters are incorrectly or not setup
+ // for the app
+ eventually {
+ waitFindObject(By.text(HEALTH_CONNECT_LABEL))
+ waitFindObject(By.text(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL))
+
+ // READ_STEPS is not granted, but should still be present due to READ_FLOORS_CLIMBED
+ // being granted
+ waitFindObject(By.text(HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL))
+ }
+ }
+
+ private fun startManageAppPermissionsActivity() {
+ uiDevice.performActionAndWait({
+ runWithShellPermissionIdentity {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
+ .apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(Intent.EXTRA_PACKAGE_NAME, PERM_USER_PACKAGE)
+ }
+ )
+ }
+ }, Until.newWindow(), TIMEOUT_SHORT)
+
+ waitFindObject(By.descContains(MORE_OPTIONS)).click()
+ waitFindObject(By.text(ALL_PERMISSIONS)).click()
+ }
+
+ companion object {
+ // Health connect label uses a non breaking space
+ private const val HEALTH_CONNECT_LABEL = "Health\u00A0Connect"
+ private const val HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED =
+ "android.permission.health.READ_FLOORS_CLIMBED"
+ private const val HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED_LABEL =
+ "Read floors climbed"
+ private const val HEALTH_CONNECT_PERMISSION_READ_STEPS_LABEL =
+ "Read steps"
+
+ private const val MORE_OPTIONS = "More options"
+ private const val ALL_PERMISSIONS = "All permissions"
+
+ private val TIMEOUT_SHORT = 500L
+ }
+} \ No newline at end of file
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt
new file mode 100644
index 000000000..4f3e281cd
--- /dev/null
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/HealthConnectAppPermissionFragmentTest.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 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.permissionui.ui
+
+import android.content.Intent
+import android.os.Build
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
+import com.android.permissioncontroller.permissionui.wakeUpScreen
+import org.junit.After
+import org.junit.Assert.assertNull
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Simple tests for {@link AppPermissionsFragment} for Health Connect behaviors
+ * Currently, does NOT run on TV.
+ * TODO(b/178576541): Adapt and run on TV.
+ * Run with:
+ * atest HealthConnectAppPermissionFragmentTest
+ */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+class HealthConnectAppPermissionFragmentTest : BasePermissionUiTest() {
+ @Before
+ fun assumeNotTelevision() = assumeFalse(isTelevision)
+
+ @Before
+ fun wakeScreenUp() {
+ wakeUpScreen()
+ }
+
+ @After
+ fun uninstallTestApp() {
+ uninstallTestApps()
+ }
+ @Test
+ fun usedHealthConnectPermissionsAreListed() {
+ installTestAppThatUsesHealthConnectPermission()
+
+ startManageAppPermissionsActivity()
+
+ eventually {
+ waitFindObject(By.text(HEALTH_CONNECT_LABEL))
+ }
+ }
+
+ @Test
+ fun invalidUngrantedUsedHealthConnectPermissionsAreNotListed() {
+ installInvalidTestAppThatUsesHealthConnectPermission()
+
+ startManageAppPermissionsActivity()
+
+ // TODO(b/288286032): update to use waitUntilObjectGone
+ eventually {
+ assertNull(waitFindObjectOrNull(By.text(HEALTH_CONNECT_LABEL), TIMEOUT_SHORT))
+ }
+ }
+
+ @Test
+ fun invalidGrantedUsedHealthConnectPermissionsAreListed() {
+ installInvalidTestAppThatUsesHealthConnectPermission()
+ grantTestAppPermission(HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED)
+
+ startManageAppPermissionsActivity()
+
+ eventually {
+ waitFindObject(By.text(HEALTH_CONNECT_LABEL))
+ }
+ }
+
+ private fun startManageAppPermissionsActivity() {
+ runWithShellPermissionIdentity {
+ instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
+ .apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(Intent.EXTRA_PACKAGE_NAME, PERM_USER_PACKAGE)
+ })
+ }
+ }
+
+ companion object {
+ // Health connect label uses a non breaking space
+ private const val HEALTH_CONNECT_LABEL = "Health\u00A0Connect"
+ private const val HEALTH_CONNECT_PERMISSION_READ_FLOORS_CLIMBED =
+ "android.permission.health.READ_FLOORS_CLIMBED"
+
+ private val TIMEOUT_SHORT = 500L
+ }
+} \ No newline at end of file
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
index 3b48d7235..1966c645c 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/LocationPermissionAppsFragmentTest.kt
@@ -28,7 +28,7 @@ import org.junit.runner.RunWith
*/
@RunWith(AndroidJUnit4::class)
class LocationPermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk",
+ "/data/local/tmp/pc-permissionui/AppThatRequestsLocation.apk",
"android.permission.cts.appthatrequestpermission",
ACCESS_COARSE_LOCATION
)
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
index a5453d9e7..2bf1d4433 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/PermissionAppsFragmentTest.kt
@@ -20,13 +20,15 @@ import android.content.Intent
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.uninstallApp
import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.Direction
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
-import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
import com.android.permissioncontroller.permissionui.wakeUpScreen
+import com.google.common.truth.Truth.assertThat
import org.junit.After
-import org.junit.Assert.assertNull
import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.Test
@@ -46,57 +48,64 @@ abstract class PermissionAppsFragmentTest(
val definerApk: String? = null,
val definerPkg: String? = null
) : BasePermissionUiTest() {
+ val pkgSelector = By.text(userPkg)
- @Before
- fun assumeNotTelevision() = assumeFalse(isTelevision)
-
- @Before
- fun wakeScreenUp() {
- wakeUpScreen()
+ private fun scrollFindFromTop(selector: BySelector): UiObject2? {
+ val scrollable = uiDevice.findObject(By.scrollable(true))
+ scrollable.scrollUntil(Direction.UP, Until.scrollFinished(Direction.UP))
+ return scrollable.scrollUntil(
+ Direction.DOWN,
+ Until.findObject(selector)
+ )
}
@Before
- fun installDefinerApk() {
+ fun startManagePermissionAppsActivity() {
+ assumeFalse(isTelevision)
+ wakeUpScreen()
if (definerApk != null) {
install(definerApk)
}
- }
-
- @Before
- fun startManagePermissionAppsActivity() {
- runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
- .apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- putExtra(Intent.EXTRA_PERMISSION_NAME, perm)
- })
- }
+ uninstallApp(userPkg)
+ uiDevice.performActionAndWait({
+ runWithShellPermissionIdentity {
+ instrumentationContext.startActivity(
+ Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+ .apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(Intent.EXTRA_PERMISSION_NAME, perm)
+ }
+ )
+ }
+ }, Until.newWindow(), Companion.NEW_WINDOW_TIMEOUT_MILLIS)
}
@Test
- fun appAppearsWhenInstalled() {
- assertNull(waitFindObjectOrNull(By.text(userPkg)))
+ fun testAppAppearanceReflectsInstallation() {
+ // Expect *not* to find package listed on screen
+ eventually({
+ val pkg = scrollFindFromTop(pkgSelector)
+ assertThat(pkg).isNull()
+ }, Companion.SCROLL_TIMEOUT_MILLIS)
+ // Install package
install(userApk)
- eventually {
- waitFindObject(By.text(userPkg))
- }
- }
- // TODO(b/280652042) Slow tests aren't good
- @Test(timeout = 120000)
- fun appDisappearsWhenUninstalled() {
- assertNull(waitFindObjectOrNull(By.text(userPkg)))
-
- install(userApk)
- eventually {
- waitFindObject(By.text(userPkg))
- }
+ // Expect to find package listed on screen
+ eventually({
+ val pkg = scrollFindFromTop(pkgSelector)
+ assertThat(pkg).isNotNull()
+ }, Companion.SCROLL_TIMEOUT_MILLIS)
+ // Uninstall app
uninstallApp(userPkg)
- eventually {
- assertNull(waitFindObjectOrNull(By.text(userPkg)))
- }
+
+ // Expect *not* to find package listed on screen
+ eventually({
+ val pkg = scrollFindFromTop(pkgSelector)
+ assertThat(pkg).isNull()
+ }, Companion.SCROLL_TIMEOUT_MILLIS)
}
@After
@@ -109,4 +118,9 @@ abstract class PermissionAppsFragmentTest(
uiDevice.pressBack()
uiDevice.pressHome()
}
+
+ companion object {
+ const val NEW_WINDOW_TIMEOUT_MILLIS = 25_000L
+ const val SCROLL_TIMEOUT_MILLIS = 25_000L
+ }
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
index ada143613..487c16db7 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/StoragePermissionAppsFragmentTest.kt
@@ -28,7 +28,7 @@ import org.junit.runner.RunWith
*/
@RunWith(AndroidJUnit4::class)
class StoragePermissionAppsFragmentTest : PermissionAppsFragmentTest(
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/data/local/tmp/pc-permissionui" +
"/PermissionUiUseStoragePermissionApp.apk",
"com.android.permissioncontroller.tests.appthatrequestpermission",
READ_EXTERNAL_STORAGE
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
index 06e25485e..29c3add2f 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/TestAppUtils.kt
@@ -21,9 +21,13 @@ import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.uninstallApp
// Test Apps' APK files
-private const val APK_DIRECTORY = "/data/local/tmp/permissioncontroller/tests/permissionui/"
+private const val APK_DIRECTORY = "/data/local/tmp/pc-permissionui/"
private const val LOCATION_PERM_USER_APK = "$APK_DIRECTORY/AppThatRequestsLocation.apk"
private const val CAMERA_PERM_USER_APK = "$APK_DIRECTORY/PermissionUiUseCameraPermissionApp.apk"
+private const val HEALTH_CONNECT_PERMISSION_USER_APK =
+ "$APK_DIRECTORY/PermissionUiUseHealthConnectPermissionApp.apk"
+private const val INVALID_HEALTH_CONNECT_PERMISSION_USER_APK =
+ "$APK_DIRECTORY/PermissionUiInvalidUseHealthConnectPermissionApp.apk"
private const val ADDITIONAL_PERM_USER_APK =
"$APK_DIRECTORY/PermissionUiUseAdditionalPermissionApp.apk"
private const val TWO_ADDITIONAL_PERM_USER_APK =
@@ -32,10 +36,10 @@ private const val ADDITIONAL_PERM_DEFINER_APK =
"$APK_DIRECTORY/PermissionUiDefineAdditionalPermissionApp.apk"
// All 4 of the AppThatUses_X_Permission(s) applications share the same package name.
-private const val PERM_USER_PACKAGE =
- "com.android.permissioncontroller.tests.appthatrequestpermission"
private const val PERM_DEFINER_PACKAGE =
"com.android.permissioncontroller.tests.appthatdefinespermission"
+const val PERM_USER_PACKAGE =
+ "com.android.permissioncontroller.tests.appthatrequestpermission"
const val CAMERA_TEST_APP_LABEL = "CameraRequestApp"
@@ -49,6 +53,9 @@ const val TEST_APP_DEFINED_PERMISSION_C_LABEL = "Permission C"
fun installTestAppThatRequestsLocation() = install(LOCATION_PERM_USER_APK)
fun installTestAppThatUsesCameraPermission() = install(CAMERA_PERM_USER_APK)
+fun installTestAppThatUsesHealthConnectPermission() = install(HEALTH_CONNECT_PERMISSION_USER_APK)
+fun installInvalidTestAppThatUsesHealthConnectPermission() =
+ install(INVALID_HEALTH_CONNECT_PERMISSION_USER_APK)
fun installTestAppThatUsesAdditionalPermission() = install(ADDITIONAL_PERM_USER_APK)
fun installTestAppThatUsesTwoAdditionalPermissions() = install(TWO_ADDITIONAL_PERM_USER_APK)
fun installTestAppThatDefinesAdditionalPermissions() = install(ADDITIONAL_PERM_DEFINER_APK)
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
index c41dacc96..0808d98d2 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageCustomPermissionsFragmentTest.kt
@@ -40,10 +40,10 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class ManageCustomPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
private val ONE_PERMISSION_DEFINER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
+ "/data/local/tmp/pc-permissionui/" +
"PermissionUiDefineAdditionalPermissionApp.apk"
private val PERMISSION_USER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
+ "/data/local/tmp/pc-permissionui/" +
"PermissionUiUseAdditionalPermissionApp.apk"
private val DEFINER_PKG = "com.android.permissioncontroller.tests.appthatdefinespermission"
private val USER_PKG = "com.android.permissioncontroller.tests.appthatrequestpermission"
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
index 5d0fae9a1..de5d6be65 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/ManageStandardPermissionsFragmentTest.kt
@@ -18,10 +18,12 @@ package com.android.permissioncontroller.permissionui.ui.handheld
import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.content.Intent
+import android.content.pm.PackageManager
import android.permission.cts.PermissionUtils.grantPermission
import android.permission.cts.PermissionUtils.install
import android.permission.cts.PermissionUtils.revokePermission
import android.permission.cts.PermissionUtils.uninstallApp
+import android.util.Log
import androidx.test.uiautomator.By
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compatibility.common.util.SystemUtil.eventually
@@ -41,23 +43,46 @@ import org.junit.runner.RunWith
*/
@RunWith(AndroidJUnit4::class)
class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
- private val LOCATION_USER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/AppThatRequestsLocation.apk"
- private val ADDITIONAL_DEFINER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
- "PermissionUiDefineAdditionalPermissionApp.apk"
- private val ADDITIONAL_USER_APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui/" +
- "PermissionUiUseAdditionalPermissionApp.apk"
- private val LOCATION_USER_PKG = "android.permission.cts.appthatrequestpermission"
- private val ADDITIONAL_DEFINER_PKG =
- "com.android.permissioncontroller.tests.appthatdefinespermission"
- private val ADDITIONAL_USER_PKG =
- "com.android.permissioncontroller.tests.appthatrequestpermission"
- private val ADDITIONAL_PERMISSIONS_LABEL = "Additional permissions"
- private val ADDITIONAL_PERMISSIONS_SUMMARY = "more"
-
- private val locationGroupLabel = "Location"
+ @Before
+ fun setup() {
+ wakeUpScreen()
+
+ runWithShellPermissionIdentity {
+ removePackageIfInstalled()
+ instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ })
+ }
+ }
+
+ @After
+ fun tearDown() {
+ uninstallApp(LOCATION_USER_PKG)
+ uninstallApp(ADDITIONAL_DEFINER_PKG)
+ uninstallApp(ADDITIONAL_USER_PKG)
+ uiDevice.pressBack()
+ }
+
+ /**
+ * The test packages are not expected to be installed already, remove them if they are
+ * already installed (i.e. leftover from another test) when a test starts.
+ */
+ private fun removePackageIfInstalled() {
+ val packageNames = listOf(LOCATION_USER_PKG, ADDITIONAL_DEFINER_PKG, ADDITIONAL_USER_PKG)
+ for (packageName in packageNames) {
+ try {
+ val packageInfo =
+ instrumentationContext.packageManager.getPackageInfo(packageName, 0)
+ if (packageInfo != null) {
+ Log.w(LOG_TAG, "package $packageName not expected to be installed.")
+ uninstallApp(packageName)
+ Thread.sleep(1000)
+ }
+ } catch (e: PackageManager.NameNotFoundException) {
+ // ignore
+ }
+ }
+ }
/**
* Read the number of additional permissions from the Ui.
@@ -80,84 +105,65 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
}
}
- @Before
- fun setup() {
- wakeUpScreen()
-
- runWithShellPermissionIdentity {
- instrumentationContext.startActivity(Intent(Intent.ACTION_MANAGE_PERMISSIONS).apply {
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
- }
-
- reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG)
-
- // Sleep before each test for 1 second for getUsageCountsFromUi to get the correct counts
- Thread.sleep(1000)
- }
-
@Test
fun groupSummaryGetsUpdatedWhenAppGetsInstalled() {
- val original = getUsageCountsFromUi(locationGroupLabel)
+ val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL)
install(LOCATION_USER_APK)
- eventually {
- val afterInstall = getUsageCountsFromUi(locationGroupLabel)
+ eventually({
+ val afterInstall = getUsageCountsFromUi(LOCATION_GROUP_LABEL)
assertThat(afterInstall.granted).isEqualTo(original.granted)
assertThat(afterInstall.total).isEqualTo(original.total + 1)
- }
+ }, TIMEOUT)
}
@Test
fun groupSummaryGetsUpdatedWhenAppGetsUninstalled() {
- reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG)
- val original = getUsageCountsFromUi(locationGroupLabel)
-
+ val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL)
install(LOCATION_USER_APK)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel)).isNotEqualTo(original)
- }
+ eventually({
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL)).isNotEqualTo(original)
+ }, TIMEOUT)
uninstallApp(LOCATION_USER_PKG)
- reuninstallApp(LOCATION_USER_APK, LOCATION_USER_PKG)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel)).isEqualTo(original)
- }
+ eventually({
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL)).isEqualTo(original)
+ }, TIMEOUT)
}
@Test
fun groupSummaryGetsUpdatedWhenPermissionGetsGranted() {
- val original = getUsageCountsFromUi(locationGroupLabel)
+ val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL)
install(LOCATION_USER_APK)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).total)
+ eventually({
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).total)
.isEqualTo(original.total + 1)
- }
+ }, TIMEOUT)
grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).granted)
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted)
.isEqualTo(original.granted + 1)
}
}
@Test
fun groupSummaryGetsUpdatedWhenPermissionGetsRevoked() {
- val original = getUsageCountsFromUi(locationGroupLabel)
+ val original = getUsageCountsFromUi(LOCATION_GROUP_LABEL)
install(LOCATION_USER_APK)
grantPermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
- eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).total)
+ eventually({
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).total)
.isNotEqualTo(original.total)
- assertThat(getUsageCountsFromUi(locationGroupLabel).granted)
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted)
.isNotEqualTo(original.granted)
- }
+ }, TIMEOUT)
revokePermission(LOCATION_USER_PKG, ACCESS_COARSE_LOCATION)
eventually {
- assertThat(getUsageCountsFromUi(locationGroupLabel).granted)
+ assertThat(getUsageCountsFromUi(LOCATION_GROUP_LABEL).granted)
.isEqualTo(original.granted)
}
}
@@ -168,10 +174,10 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
- eventually {
+ eventually({
assertThat(getAdditionalPermissionCount())
.isEqualTo(additionalPermissionBefore + 1)
- }
+ }, TIMEOUT)
}
@Test
@@ -180,15 +186,15 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
- eventually {
+ eventually({
assertThat(getAdditionalPermissionCount())
.isNotEqualTo(additionalPermissionBefore)
- }
+ }, TIMEOUT)
uninstallApp(ADDITIONAL_USER_PKG)
- eventually {
+ eventually({
assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore)
- }
+ }, TIMEOUT)
}
@Test
@@ -197,32 +203,39 @@ class ManageStandardPermissionsFragmentTest : BaseHandheldPermissionUiTest() {
install(ADDITIONAL_DEFINER_APK)
install(ADDITIONAL_USER_APK)
- eventually {
+ eventually({
assertThat(getAdditionalPermissionCount())
.isNotEqualTo(additionalPermissionBefore)
- }
+ }, TIMEOUT)
uninstallApp(ADDITIONAL_DEFINER_PKG)
- eventually {
+ eventually({
assertThat(getAdditionalPermissionCount()).isEqualTo(additionalPermissionBefore)
- }
- }
-
- fun reuninstallApp(apk: String, pkg: String) {
- // b/275752754: sometimes this test is flaky because inside @After it didn't uninstall the
- // packages correctly. This caused the permission manager screen to still show the package
- // as requesting the permission and caused the original usage count to be incorrect.
- // Installing/uninstalling the packages again to ensure the package is correctly uninstalled
- install(apk)
- uninstallApp(pkg)
+ }, TIMEOUT)
}
- @After
- fun tearDown() {
- uninstallApp(LOCATION_USER_PKG)
- uninstallApp(ADDITIONAL_DEFINER_PKG)
- uninstallApp(ADDITIONAL_USER_PKG)
-
- uiDevice.pressBack()
+ companion object {
+ private val LOG_TAG = ManageStandardPermissionsFragmentTest::class.java.simpleName
+
+ private const val LOCATION_USER_APK =
+ "/data/local/tmp/pc-permissionui/AppThatRequestsLocation.apk"
+ private const val ADDITIONAL_DEFINER_APK =
+ "/data/local/tmp/pc-permissionui/" +
+ "PermissionUiDefineAdditionalPermissionApp.apk"
+ private const val ADDITIONAL_USER_APK =
+ "/data/local/tmp/pc-permissionui/" +
+ "PermissionUiUseAdditionalPermissionApp.apk"
+ private const val LOCATION_USER_PKG = "android.permission.cts.appthatrequestpermission"
+ private const val ADDITIONAL_DEFINER_PKG =
+ "com.android.permissioncontroller.tests.appthatdefinespermission"
+ private const val ADDITIONAL_USER_PKG =
+ "com.android.permissioncontroller.tests.appthatrequestpermission"
+ private const val ADDITIONAL_PERMISSIONS_LABEL = "Additional permissions"
+ private const val ADDITIONAL_PERMISSIONS_SUMMARY = "more"
+ private const val LOCATION_GROUP_LABEL = "Location"
+
+ // Package Added/Removed broadcast are pretty slow on cf devices, we may want to increase
+ // this in future if the test still fails.
+ private const val TIMEOUT = 30000L
}
}
diff --git a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
index 2869e1863..1c71c262e 100644
--- a/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
+++ b/PermissionController/tests/permissionui/src/com/android/permissioncontroller/permissionui/ui/handheld/v31/PermissionUsageFragmentTest.kt
@@ -41,7 +41,7 @@ import org.junit.runner.RunWith
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
class PermissionUsageFragmentTest : PermissionHub2Test() {
private val APK =
- "/data/local/tmp/permissioncontroller/tests/permissionui" +
+ "/data/local/tmp/pc-permissionui" +
"/PermissionUiUseCameraPermissionApp.apk"
private val APP = "com.android.permissioncontroller.tests.appthatrequestpermission"
private val APP_LABEL = "CameraRequestApp"
@@ -61,9 +61,12 @@ class PermissionUsageFragmentTest : PermissionHub2Test() {
runWithShellPermissionIdentity {
context.startActivity(
- Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE).apply {
+ Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
+ .apply {
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- })
+ }
+ )
}
eventually {
diff --git a/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java b/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java
new file mode 100644
index 000000000..6e1f4c3b7
--- /dev/null
+++ b/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresTiramisuByDefault.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.annotations;
+
+import static android.os.Build.VERSION_CODES.TIRAMISU;
+
+import static java.lang.annotation.ElementType.PACKAGE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import androidx.annotation.RequiresApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierDefault;
+
+/**
+ * Specifies that all types are {@code RequiresApi(TIRAMISU)} within the annotated package, unless
+ * tagged another {@code @RequiresApi} annotation.
+ */
+@Retention(CLASS)
+@Target(PACKAGE)
+@TypeQualifierDefault({TYPE})
+@RequiresApi(TIRAMISU)
+public @interface RequiresTiramisuByDefault {}
diff --git a/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresVanillaIceCreamByDefault.java b/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresVanillaIceCreamByDefault.java
new file mode 100644
index 000000000..bb1c1eb97
--- /dev/null
+++ b/SafetyCenter/Annotations/java/com/android/safetycenter/annotations/RequiresVanillaIceCreamByDefault.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.annotations;
+
+import static android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM;
+
+import static java.lang.annotation.ElementType.PACKAGE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import androidx.annotation.RequiresApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.annotation.meta.TypeQualifierDefault;
+
+/**
+ * Specifies that all types are {@code RequiresApi(VANILLA_ICE_CREAM)} within the annotated package,
+ * unless tagged another {@code @RequiresApi} annotation.
+ */
+@Retention(CLASS)
+@Target(PACKAGE)
+@TypeQualifierDefault({TYPE})
+@RequiresApi(VANILLA_ICE_CREAM)
+public @interface RequiresVanillaIceCreamByDefault {}
diff --git a/SafetyCenter/Config/TEST_MAPPING b/SafetyCenter/Config/TEST_MAPPING
index c35d3d777..d8a356636 100644
--- a/SafetyCenter/Config/TEST_MAPPING
+++ b/SafetyCenter/Config/TEST_MAPPING
@@ -9,7 +9,7 @@
"name": "SafetyCenterConfigTests[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
diff --git a/SafetyCenter/ConfigLintChecker/java/android/os/Build.java b/SafetyCenter/ConfigLintChecker/java/android/os/Build.java
index 531b6e481..4a58e04fc 100644
--- a/SafetyCenter/ConfigLintChecker/java/android/os/Build.java
+++ b/SafetyCenter/ConfigLintChecker/java/android/os/Build.java
@@ -24,7 +24,11 @@ public final class Build {
public static final class VERSION_CODES {
/** Constant used in the Safety Center config code. */
public static final int TIRAMISU = 33;
+
/** Constant used in the Safety Center config code. */
public static final int UPSIDE_DOWN_CAKE = 34;
+
+ /** Constant used in the Safety Center config code. */
+ public static final int VANILLA_ICE_CREAM = 35;
}
}
diff --git a/SafetyCenter/ConfigLintChecker/java/com/android/modules/utils/build/SdkLevel.java b/SafetyCenter/ConfigLintChecker/java/com/android/modules/utils/build/SdkLevel.java
index dbfaa56b1..cfe99071c 100644
--- a/SafetyCenter/ConfigLintChecker/java/com/android/modules/utils/build/SdkLevel.java
+++ b/SafetyCenter/ConfigLintChecker/java/com/android/modules/utils/build/SdkLevel.java
@@ -18,6 +18,7 @@ package com.android.modules.utils.build;
import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+import static android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM;
/** Stub class to compile the linter for host execution. */
public final class SdkLevel {
@@ -42,4 +43,9 @@ public final class SdkLevel {
public static boolean isAtLeastU() {
return sSdkInt >= UPSIDE_DOWN_CAKE;
}
+
+ /** Method used in the Safety Center config code. */
+ public static boolean isAtLeastV() {
+ return sSdkInt >= VANILLA_ICE_CREAM;
+ }
}
diff --git a/SafetyCenter/Resources/res/raw-v35/safety_center_config.xml b/SafetyCenter/Resources/res/raw-v35/safety_center_config.xml
new file mode 100644
index 000000000..83369f920
--- /dev/null
+++ b/SafetyCenter/Resources/res/raw-v35/safety_center_config.xml
@@ -0,0 +1,136 @@
+<!--
+ ~ 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.
+ -->
+
+<safety-center-config>
+ <safety-sources-config>
+ <safety-sources-group
+ id="AndroidLockScreenSources"
+ title="@com.android.safetycenter.resources:string/lock_screen_sources_title"
+ summary="@com.android.safetycenter.resources:string/lock_screen_sources_summary">
+ <dynamic-safety-source
+ id="AndroidLockScreen"
+ packageName="com.android.settings"
+ profile="primary_profile_only"
+ title="@com.android.safetycenter.resources:string/lock_screen_title"
+ summary="@com.android.safetycenter.resources:string/lock_screen_summary_disabled"
+ searchTerms="@com.android.safetycenter.resources:string/lock_screen_search_terms"
+ initialDisplayState="disabled"
+ notificationsAllowed="true"/>
+ <dynamic-safety-source
+ id="AndroidBiometrics"
+ packageName="com.android.settings"
+ profile="all_profiles"
+ title="@com.android.safetycenter.resources:string/biometrics_title"
+ titleForWork="@com.android.safetycenter.resources:string/biometrics_title_for_work"
+ searchTerms="@com.android.safetycenter.resources:string/biometrics_search_terms"
+ initialDisplayState="hidden"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="AndroidPrivacySources"
+ title="@com.android.safetycenter.resources:string/privacy_sources_title"
+ summary="@com.android.safetycenter.resources:string/privacy_sources_summary"
+ statelessIconType="privacy">
+ <static-safety-source
+ id="AndroidPermissionManager"
+ profile="primary_profile_only"
+ intentAction="android.intent.action.MANAGE_PERMISSIONS"
+ title="@com.android.safetycenter.resources:string/permission_manager_title"
+ summary="@com.android.safetycenter.resources:string/permission_manager_summary"
+ searchTerms="@com.android.safetycenter.resources:string/permission_manager_search_terms"/>
+ <static-safety-source
+ id="AndroidPermissionUsage"
+ profile="primary_profile_only"
+ intentAction="android.intent.action.REVIEW_PERMISSION_USAGE"
+ title="@com.android.safetycenter.resources:string/permission_usage_title"
+ summary="@com.android.safetycenter.resources:string/permission_usage_summary"
+ searchTerms="@com.android.safetycenter.resources:string/permission_usage_search_terms"/>
+ <dynamic-safety-source
+ id="AndroidHealthConnect"
+ profile="primary_profile_only"
+ packageName="com.android.healthconnect.controller"
+ initialDisplayState="hidden"
+ refreshOnPageOpenAllowed="false"
+ title="@com.android.safetycenter.resources:string/health_connect_title"
+ searchTerms="@com.android.safetycenter.resources:string/health_connect_search_terms"/>
+ <dynamic-safety-source
+ id="AndroidPrivacyAppDataSharingUpdates"
+ packageName="com.android.permissioncontroller"
+ profile="primary_profile_only"
+ initialDisplayState="hidden"
+ refreshOnPageOpenAllowed="true"
+ title="@com.android.safetycenter.resources:string/app_data_sharing_updates_title"
+ searchTerms="@com.android.safetycenter.resources:string/app_data_sharing_updates_search_terms"/>
+ <static-safety-source
+ id="AndroidPrivacyControls"
+ profile="primary_profile_only"
+ intentAction="android.settings.PRIVACY_CONTROLS"
+ title="@com.android.safetycenter.resources:string/privacy_controls_title"
+ summary="@com.android.safetycenter.resources:string/privacy_controls_summary"
+ searchTerms="@com.android.safetycenter.resources:string/privacy_controls_search_terms"/>
+ <issue-only-safety-source
+ id="AndroidAccessibility"
+ packageName="com.android.permissioncontroller"
+ profile="all_profiles"
+ notificationsAllowed="true"
+ refreshOnPageOpenAllowed="true"/>
+ <issue-only-safety-source
+ id="AndroidNotificationListener"
+ packageName="com.android.permissioncontroller"
+ profile="primary_profile_only"
+ notificationsAllowed="true"
+ refreshOnPageOpenAllowed="true"/>
+ <issue-only-safety-source
+ id="AndroidBackgroundLocation"
+ packageName="com.android.permissioncontroller"
+ profile="all_profiles"
+ notificationsAllowed="true"
+ refreshOnPageOpenAllowed="true"/>
+ <issue-only-safety-source
+ id="AndroidPermissionAutoRevoke"
+ packageName="com.android.permissioncontroller"
+ profile="all_profiles"
+ notificationsAllowed="true"
+ refreshOnPageOpenAllowed="true"/>
+ </safety-sources-group>
+ <safety-sources-group
+ id="AndroidAdvancedSources"
+ title="@com.android.safetycenter.resources:string/advanced_title">
+ <dynamic-safety-source
+ id="AndroidWorkPolicyInfo"
+ packageName="com.android.permissioncontroller"
+ profile="primary_profile_only"
+ title="@com.android.safetycenter.resources:string/work_policy_title"
+ initialDisplayState="hidden"
+ refreshOnPageOpenAllowed="true"/>
+ <static-safety-source
+ id="AndroidMoreSettings"
+ profile="primary_profile_only"
+ intentAction="com.android.settings.MORE_SECURITY_PRIVACY_SETTINGS"
+ title="@com.android.safetycenter.resources:string/more_settings_title"
+ summary="@com.android.safetycenter.resources:string/more_settings_summary"
+ searchTerms="@com.android.safetycenter.resources:string/more_settings_search_terms"/>
+ <dynamic-safety-source
+ id="AndroidPrivateSpace"
+ packageName="com.android.settings"
+ profile="primary_profile_only"
+ title="@com.android.safetycenter.resources:string/private_space_title"
+ summary="@com.android.safetycenter.resources:string/private_space_summary"
+ searchTerms="@com.android.safetycenter.resources:string/private_space_search_terms"
+ initialDisplayState="hidden"
+ maxSeverityLevel="0"/>
+ </safety-sources-group>
+ </safety-sources-config>
+</safety-center-config>
diff --git a/SafetyCenter/Resources/res/values-af-v34/strings.xml b/SafetyCenter/Resources/res/values-af-v34/strings.xml
index d54ed46b1..ad8401412 100644
--- a/SafetyCenter/Resources/res/values-af-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-af-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Gesondheid, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Datadelingopdaterings vir ligging"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, datadeling, datadelingopdaterings, datadelingopdaterings vir ligging, deling"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Advertensieprivaatheid"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Pasmaak inligting wat apps gebruik om vir jou advertensies te wys"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"advertensies, advertensieprivaatheid, privacy sandbox, advertensie-onderwerpe, appvoorgestelde advertensies, advertensiemeting"</string>
<string name="advanced_title" msgid="6259362998269627310">"Ander instellings"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Meer sekuriteit en privaatheid"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Outovul, kennisgewings en meer"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Jou werkbeleidinligting"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-af-v35/strings.xml b/SafetyCenter/Resources/res/values-af-v35/strings.xml
new file mode 100644
index 000000000..2990bde0d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-af-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privaat ruimte"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Stel privaat ruimte op, en meer"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privaat ruimte"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-af/strings.xml b/SafetyCenter/Resources/res/values-af/strings.xml
index e46fb352d..ff0fc873d 100644
--- a/SafetyCenter/Resources/res/values-af/strings.xml
+++ b/SafetyCenter/Resources/res/values-af/strings.xml
@@ -28,7 +28,7 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"Privaatheid"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Kontroleskerm, toestemmings, kontroles"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Privaatheidkontroleskerm"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Wys watter programme onlangs toestemmings gebruik het"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Wys watter apps onlangs toestemmings gebruik het"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Privaatheid, Privaatheidkontroleskerm"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Toestemmingbestuurder"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Beheer apptoegang tot jou data"</string>
diff --git a/SafetyCenter/Resources/res/values-am-v34/strings.xml b/SafetyCenter/Resources/res/values-am-v34/strings.xml
index 13d95ff68..6b94d58ca 100644
--- a/SafetyCenter/Resources/res/values-am-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-am-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ጤና፣ የጤና አገናኝ"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"የአካባቢ የውሂብ ማጋራት ዝማኔዎች"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ውሂብ፣ የውሂብ ማጋራት፣ የውሂብ ማጋራት ዝማኔዎች፣ የአካባቢ የውሂብ ማጋራት ዝማኔዎች፣ ማጋራት"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"የማስታወቂያ ግላዊነት"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"መተግበሪያዎች ማስታወቂያዎችን ለማሳየት የሚጠቀሙበትን መረጃ ያብጁ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ማስታወቂያዎች፣ የማስታወቂያ ግላዊነት፣ የግላዊነት Sandbox፣ የማስታወቂያ ርዕሶች፣ በመተግበሪያ የተጠቆሙ ማስታወቂያዎች፣ የማስታወቂያ ልኬት"</string>
<string name="advanced_title" msgid="6259362998269627310">"ሌሎች ቅንብሮች"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"ተጨማሪ ደህንነት &amp; እና ግላዊነት"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"ተጨማሪ ደህንነት እና ግላዊነት"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ራስ-ሙላ፣ ማሳወቂያዎች እና ሌሎችም"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"የእርስዎ የሥራ መመሪያ መረጃ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-am-v35/strings.xml b/SafetyCenter/Resources/res/values-am-v35/strings.xml
new file mode 100644
index 000000000..290a8816c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-am-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"የግል ቦታ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"የግል ቦታን እና ሌሎችን ያዋቅሩ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"የግል ቦታ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-am/strings.xml b/SafetyCenter/Resources/res/values-am/strings.xml
index 32e7fd8b5..5d0914a79 100644
--- a/SafetyCenter/Resources/res/values-am/strings.xml
+++ b/SafetyCenter/Resources/res/values-am/strings.xml
@@ -20,9 +20,9 @@
<string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"የደህንነት ማዕከል መርጃዎች"</string>
<string name="lock_screen_sources_title" msgid="3317906280484627707">"የመሣሪያ ቁልፍ"</string>
<string name="lock_screen_sources_summary" msgid="7220439741282516496"></string>
- <string name="lock_screen_title" msgid="4069104894527169877">"የማያ ገጽ ቁልፍ"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"የማያ ገፅ ቁልፍ"</string>
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"ገና ምንም መረጃ የለም"</string>
- <string name="lock_screen_search_terms" msgid="2678486357779794826">"የመሣሪያ ቁልፍ፣ የማያ ገጽ መቆለፊያ፣ የማያ ገጽ ቁልፍ፣ የማያ ገጽ ቁልፍ፣ የይለፍ ቃል፣ ፒን፣ ስርዓተ ጥለት"</string>
+ <string name="lock_screen_search_terms" msgid="2678486357779794826">"የመሣሪያ ቁልፍ፣ የማያ ገፅ መቆለፊያ፣ የማያ ገፅ ቁልፍ፣ የማያ ገፅ ቁልፍ፣ የይለፍ ቃል፣ ፒን፣ ስርዓተ ጥለት"</string>
<string name="biometrics_title" msgid="5859504610285212938">"ባዮሜትሪክስ"</string>
<string name="biometrics_search_terms" msgid="6040319118762671981">"የጣት አሻራ፣ ጣት፣ የጣት አሻራ ያክሉ፣ በመልክ መክፈት፣ መልክ"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"ግላዊነት"</string>
diff --git a/SafetyCenter/Resources/res/values-ar-v34/strings.xml b/SafetyCenter/Resources/res/values-ar-v34/strings.xml
index d4cd4ec86..4449b333c 100644
--- a/SafetyCenter/Resources/res/values-ar-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ar-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"‏الصحة، Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"تعديلات مشاركة بيانات الموقع الجغرافي"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"البيانات، مشاركة البيانات، تعديلات مشاركة البيانات، تعديلات مشاركة بيانات الموقع الجغرافي، المشاركة"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"الخصوصية في عرض الإعلانات"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"تخصيص المعلومات التي تستخدمها التطبيقات لعرض الإعلانات لك"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"الإعلانات، الخصوصية في عرض الإعلانات، مبادرة حماية الخصوصية، مواضيع الإعلانات، الإعلانات المقترَحة من التطبيقات، قياس أداء الإعلانات"</string>
<string name="advanced_title" msgid="6259362998269627310">"إعدادات أخرى"</string>
<string name="more_settings_title" msgid="9033454654010697185">"تعزيز الأمان والخصوصية"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"الملء التلقائي والإشعارات والمزيد"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"معلومات سياسة العمل"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ar-v35/strings.xml b/SafetyCenter/Resources/res/values-ar-v35/strings.xml
new file mode 100644
index 000000000..29fc7583d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ar-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"مساحة خاصة"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ضبط إعدادات مساحة خاصة وغير ذلك"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"مساحة خاصة"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ar/strings.xml b/SafetyCenter/Resources/res/values-ar/strings.xml
index e0e027987..2a97af99a 100644
--- a/SafetyCenter/Resources/res/values-ar/strings.xml
+++ b/SafetyCenter/Resources/res/values-ar/strings.xml
@@ -30,7 +30,7 @@
<string name="permission_usage_title" msgid="3633779688945350407">"لوحة بيانات الخصوصية"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"عرض التطبيقات التي استخدمت الأذونات مؤخرًا"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"الخصوصية، لوحة بيانات الخصوصية"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"مدير الأذونات"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"إدارة الأذونات"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"التحكُّم في وصول التطبيقات إلى بياناتك"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"الأذونات، مدير الأذونات"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"عناصر التحكّم في الخصوصية"</string>
diff --git a/SafetyCenter/Resources/res/values-as-v34/strings.xml b/SafetyCenter/Resources/res/values-as-v34/strings.xml
index 094f41869..e8a084491 100644
--- a/SafetyCenter/Resources/res/values-as-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-as-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"স্বাস্থ্য, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"অৱস্থানৰ বাবে ডেটা শ্বেয়াৰ কৰাৰ আপডে’ট"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ডেটা, ডেটা শ্বেয়াৰ কৰা, ডেটা শ্বেয়াৰ কৰা সম্পৰ্কীয় আপডে’ট, অৱস্থানৰ বাবে ডেটা শ্বেয়াৰ কৰাৰ আপডে’ট, শ্বেয়াৰ কৰা"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"বিজ্ঞাপনৰ গোপনীয়তা"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"আপোনাক বিজ্ঞাপন দেখুৱাবলৈ তথ্য এপৰ ব্যৱহাৰ কাষ্টমাইজ কৰক"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"বিজ্ঞাপন, বিজ্ঞাপনৰ গোপনীয়তা, প্ৰাইভেচি ছেণ্ডবক্স, বিজ্ঞাপনৰ বিষয়বস্তু, এপে পৰামৰ্শ দিয়া বিজ্ঞাপন, বিজ্ঞাপনৰ জোখ-মাখ"</string>
<string name="advanced_title" msgid="6259362998269627310">"অন্য ছেটিং"</string>
<string name="more_settings_title" msgid="9033454654010697185">"অধিক সুৰক্ষা আৰু গোপনীয়তা"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"স্বয়ংক্ৰিয়ভাৱে পূৰ হোৱাৰ সুবিধা, জাননী আৰু আন বহুতো"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"আপোনাৰ কৰ্মস্থানৰ নীতিৰ তথ্য"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-as-v35/strings.xml b/SafetyCenter/Resources/res/values-as-v35/strings.xml
new file mode 100644
index 000000000..71918ea36
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-as-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ব্যক্তিগত স্পে’চ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ব্যক্তিগত স্পে’চ আৰু আন বহুতো ছেটআপ কৰক"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ব্যক্তিগত স্পে’চ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-az-v34/strings.xml b/SafetyCenter/Resources/res/values-az-v34/strings.xml
index 6fba4f5c0..474dec23c 100644
--- a/SafetyCenter/Resources/res/values-az-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-az-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Sağlamlıq, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Məkan üzrə data paylaşımı yenilikləri"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Data paylaşımı, Data paylaşımı yenilikləri, Məkan üzrə data paylaşımı, paylaşım"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Reklam məxfiliyi"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Tətbiqlərin sizə reklam göstərmək üçün istifadə etdiyi məlumatları fərdiləşdirin"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamlar, reklam məxfiliyi, təhlükəsiz sandbox, reklam mövzuları, tətbiq tərəfindən təklif edilən reklamlar, reklam ölçüsü"</string>
<string name="advanced_title" msgid="6259362998269627310">"Digər ayarlar"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Güvənlik və məxfilik ayarlarının ardı"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Avto doldurma, bildirişlər və s."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"İş siyasəti məlumatı"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-az-v35/strings.xml b/SafetyCenter/Resources/res/values-az-v35/strings.xml
new file mode 100644
index 000000000..e1fd4c181
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-az-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Şəxsi yer"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Şəxsi yer və s. ayarlayın"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Şəxsi yer"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-b+sr+Latn-v34/strings.xml b/SafetyCenter/Resources/res/values-b+sr+Latn-v34/strings.xml
index 0709cce9f..a61fc129a 100644
--- a/SafetyCenter/Resources/res/values-b+sr+Latn-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-b+sr+Latn-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"zdravlje, povezivanje zdravlja"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Ažuriranja deljenja podataka za lokaciju"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"podaci, deljenje podataka, ažuriranja deljenja podataka, ažuriranja deljenja podataka za lokaciju, deljenje"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privatnost sa oglasima"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Prilagodite informacije koje aplikacije koriste da bi vam prikazivale oglase"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"oglasi, privatnost sa oglasima, zaštićeno okruženje privatnosti, teme oglasa, oglasi koje predlažu aplikacije, merenje oglasa"</string>
<string name="advanced_title" msgid="6259362998269627310">"Ostala podešavanja"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Još bezbednosti i privatnosti"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatsko popunjavanje, obaveštenja i drugo"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informacije o smernicama za posao"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml b/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml
new file mode 100644
index 000000000..6a52a1a8d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privatni prostor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Podesite privatni prostor i drugo"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privatni prostor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml b/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml
index 607286886..c4328fe12 100644
--- a/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml
+++ b/SafetyCenter/Resources/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,7 @@
<string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Resursi Centra za bezbednost"</string>
<string name="lock_screen_sources_title" msgid="3317906280484627707">"Zaključavanje uređaja"</string>
<string name="lock_screen_sources_summary" msgid="7220439741282516496"></string>
- <string name="lock_screen_title" msgid="4069104894527169877">"Zaključavanje ekrana"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Otključavanje ekrana"</string>
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Još nema informacija"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"zaključavanje uređaja, zaključavanje ekrana, zaključani ekran, lozinka, PIN, šablon"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Biometrija"</string>
diff --git a/SafetyCenter/Resources/res/values-be-v34/strings.xml b/SafetyCenter/Resources/res/values-be-v34/strings.xml
index 765791502..6c348b44c 100644
--- a/SafetyCenter/Resources/res/values-be-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-be-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Здароўе, Здароўе і спорт"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Змяненні ў абагульванні даных пра месцазнаходжанне"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Даныя, абагульванне даных, Змяненні ў абагульванні даных, Змяненні ў абагульванні даных пра месцазнаходжанне, абагульванне"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Прыватнасць у рэкламе"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Наладзьце інфармацыю, якую праграмы выкарыстоўваюць для паказу вам рэкламы"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"рэклама, прыватнасць у рэкламе, Privacy Sandbox, тэмы аб\'явы, рэклама, прапанаваная праграмай, эфектыўнасць рэкламы"</string>
<string name="advanced_title" msgid="6259362998269627310">"Іншыя налады"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Дадатковыя налады бяспекі і прыватнасці"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Аўтазапаўненне, апавяшчэнні і іншае"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Інфармацыя пра вашу палітыку арганізацыі"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-be-v35/strings.xml b/SafetyCenter/Resources/res/values-be-v35/strings.xml
new file mode 100644
index 000000000..c8db4cb50
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-be-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Прыватная вобласць"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Наладжванне прыватнай вобласці і не толькі"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Прыватная вобласць"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-be/strings.xml b/SafetyCenter/Resources/res/values-be/strings.xml
index d62a5c256..b1d0b58cc 100644
--- a/SafetyCenter/Resources/res/values-be/strings.xml
+++ b/SafetyCenter/Resources/res/values-be/strings.xml
@@ -28,10 +28,10 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"Прыватнасць"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Панэль кіравання, дазволы, налады"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Панэль кіравання доступам"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Паказ праграм, якія нядаўна выкарыстоўвалі дазволы"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Глядзіце, якія праграмы нядаўна выкарыстоўвалі дазволы"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Прыватнасць, панэль кіравання доступам"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Менеджар дазволаў"</string>
- <string name="permission_manager_summary" msgid="8099852107340970790">"Кіраванне доступам праграм да вашых даных"</string>
+ <string name="permission_manager_summary" msgid="8099852107340970790">"Кіруйце доступам праграм да вашых даных"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Дазволы, менеджар дазволаў"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Налады прыватнасці"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Кіраванне доступам прылады да мікрафона, камеры і іншых функцый"</string>
diff --git a/SafetyCenter/Resources/res/values-bg-v34/strings.xml b/SafetyCenter/Resources/res/values-bg-v34/strings.xml
index 6557b3e60..4799cdaec 100644
--- a/SafetyCenter/Resources/res/values-bg-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-bg-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"здраве, health connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Актуализации за споделянето на данни за местоположението"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"данни, споделяне на данни, актуализации за споделянето на данни, актуализации за споделянето на данни за местоположението, споделяне"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Поверителност при рекламите"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Персонализиране на информацията, която приложенията използват, за да ви показват реклами"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"реклами, поверителност при рекламите, privacy sandbox, рекламни теми, предлагани от приложенията реклами, измерване на рекламите"</string>
<string name="advanced_title" msgid="6259362998269627310">"Други настройки"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Още настройки за сигурност и поверителност"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автоматично попълване, известия и др."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Информация за служебните правила"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-bg-v35/strings.xml b/SafetyCenter/Resources/res/values-bg-v35/strings.xml
new file mode 100644
index 000000000..bb78de8a5
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bg-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Лично пространство"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Настройване на лично пространство и др."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Лично пространство"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-bn-v34/strings.xml b/SafetyCenter/Resources/res/values-bn-v34/strings.xml
index ff9fc5063..02435f415 100644
--- a/SafetyCenter/Resources/res/values-bn-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-bn-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"স্বাস্থ্য, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"লোকেশনের জন্য ডেটা শেয়ারিং সম্পর্কিত আপডেট"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ডেটা, ডেটা শেয়ার করা, ডেটা শেয়ার করা সংক্রান্ত আপডেট, লোকেশনের জন্য ডেটা শেয়ারিং সম্পর্কিত আপডেট, শেয়ার করা"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"বিজ্ঞাপন সংক্রান্ত গোপনীয়তা"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"আপনাকে বিজ্ঞাপন দেখানোর জন্য অ্যাপের ব্যবহার করা তথ্য কাস্টমাইজ করুন"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"বিজ্ঞাপন, বিজ্ঞাপন সংক্রান্ত গোপনীয়তা, প্রাইভেসি স্যান্ডবক্স, বিজ্ঞাপনের বিষয়, অ্যাপের সাজেস্ট করা বিজ্ঞাপন, বিজ্ঞাপন সম্পর্কিত পরিমাপ"</string>
<string name="advanced_title" msgid="6259362998269627310">"অন্যান্য সেটিংস"</string>
<string name="more_settings_title" msgid="9033454654010697185">"আরও সুরক্ষা ও গোপনীয়তা"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"অটোফিল, বিজ্ঞপ্তি ও আরও অনেক কিছু"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"আপনার অফিসের নীতি সংক্রান্ত তথ্য"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-bn-v35/strings.xml b/SafetyCenter/Resources/res/values-bn-v35/strings.xml
new file mode 100644
index 000000000..5b05d3b7e
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bn-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ব্যক্তিগত স্পেস"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"\'ব্যক্তিগত স্পেস\' সেট-আপ ও আরও অনেক কিছু করুন"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ব্যক্তিগত স্পেস"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-bs-v34/strings.xml b/SafetyCenter/Resources/res/values-bs-v34/strings.xml
index e7c2d65b4..f863c8824 100644
--- a/SafetyCenter/Resources/res/values-bs-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-bs-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Zdravlje, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Promjene u dijeljenju podataka za lokaciju"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Podaci, dijeljenje podataka, ažuriranja dijeljenja podataka, ažuriranje dijeljenja podataka za lokaciju, dijeljenje"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privatnost pri izloženosti oglasima"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Prilagodite informacije koje aplikacije koriste da vam prikazuju oglase"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"oglasi, privatnost pri izloženosti oglasima, okruženje zaštićene privatnosti, teme oglasa, oglasi koje predlažu aplikacije, mjerenje oglasa"</string>
<string name="advanced_title" msgid="6259362998269627310">"Ostale postavke"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Dodatna sigurnost i privatnost"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatsko popunjavanje, obavještenja i drugo"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informacije o radnim pravilima"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-bs-v35/strings.xml b/SafetyCenter/Resources/res/values-bs-v35/strings.xml
new file mode 100644
index 000000000..ab9d9d6ba
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-bs-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privatni prostor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Postavite privatni prostor i drugo"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privatni prostor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ca-v34/strings.xml b/SafetyCenter/Resources/res/values-ca-v34/strings.xml
index 88dfe0879..fb88118fd 100644
--- a/SafetyCenter/Resources/res/values-ca-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ca-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"salut, salut connectada"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Canvis en la compartició de dades per a la ubicació"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"dades, compartició de dades, canvis en la compartició de dades, canvis en la compartició de dades per a la ubicació, compartició"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privadesa d\'anuncis"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalitza la informació que les aplicacions utilitzen per mostrar-te anuncis"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anuncis, privadesa d\'anuncis, privacy sandbox, temes d\'anuncis, anuncis suggerits per aplicacions, mesurament d\'anuncis"</string>
<string name="advanced_title" msgid="6259362998269627310">"Altres opcions de configuració"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Més seguretat i privadesa"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Emplenament automàtic, notificacions i més"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informació de la teva política de treball"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ca-v35/strings.xml b/SafetyCenter/Resources/res/values-ca-v35/strings.xml
new file mode 100644
index 000000000..ba0cc5dd2
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ca-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espai privat"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configura l\'espai privat i més"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espai privat"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ca/strings.xml b/SafetyCenter/Resources/res/values-ca/strings.xml
index 950d0b79e..97fb5f8be 100644
--- a/SafetyCenter/Resources/res/values-ca/strings.xml
+++ b/SafetyCenter/Resources/res/values-ca/strings.xml
@@ -18,7 +18,7 @@
<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="3317906280484627707">"Bloqueig de dispositius"</string>
+ <string name="lock_screen_sources_title" msgid="3317906280484627707">"Bloqueig del dispositiu"</string>
<string name="lock_screen_sources_summary" msgid="7220439741282516496"></string>
<string name="lock_screen_title" msgid="4069104894527169877">"Bloqueig de pantalla"</string>
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Encara no hi ha informació"</string>
diff --git a/SafetyCenter/Resources/res/values-cs-v34/strings.xml b/SafetyCenter/Resources/res/values-cs-v34/strings.xml
index 9e2cf4981..4f9c811aa 100644
--- a/SafetyCenter/Resources/res/values-cs-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-cs-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"zdraví, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Aktualizace sdílení údajů o poloze"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"data, sdílení dat, aktualizace sdílení dat, aktualizace sdílení údajů o poloze, sdílení"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ochrana soukromí v reklamách"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Přizpůsobte údaje, které aplikace používají k zobrazování reklam"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamy, ochrana, soukromí v reklamách, privacy sandbox, témata reklam, reklamy navrhované aplikacemi, měření reklam"</string>
<string name="advanced_title" msgid="6259362998269627310">"Další nastavení"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Další zabezpečení a ochrana soukromí"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatické vyplňování, oznámení atd."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informace o vašich pracovních zásadách"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-cs-v35/strings.xml b/SafetyCenter/Resources/res/values-cs-v35/strings.xml
new file mode 100644
index 000000000..532449ee1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-cs-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Soukromý prostor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Nastavte si Soukromý prostor atd."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Soukromý prostor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-da-v34/strings.xml b/SafetyCenter/Resources/res/values-da-v34/strings.xml
index b43adc2cf..d4dbdf7b9 100644
--- a/SafetyCenter/Resources/res/values-da-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-da-v34/strings.xml
@@ -18,17 +18,15 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="lock_screen_sources_title" msgid="5493678510117489865">"Enhedsoplåsning"</string>
- <string name="biometrics_title_for_work" msgid="1842284049407771568">"Biometri til arbejdet"</string>
+ <string name="biometrics_title_for_work" msgid="1842284049407771568">"Biometri til arbejdsprofil"</string>
<string name="privacy_sources_summary" msgid="4083646673569677049">"Tilladelser, kontrolpanel, indstillinger"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Opdateringer om deling af lokationsdata"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, datadeling, opdateringer om datadeling, opdateringer om deling af lokationsdata, deling"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privatliv ved annoncering"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Tilpas de oplysninger, apps bruger til at vise dig annoncer"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annoncer, privatliv ved annoncering, privacy sandbox, annonceemner, annoncer foreslået af apps, annoncemåling"</string>
<string name="advanced_title" msgid="6259362998269627310">"Andre indstillinger"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mere sikkerhed og privatliv"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofyld, notifikationer m.m."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Oplysninger om din arbejdspolitik"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-da-v35/strings.xml b/SafetyCenter/Resources/res/values-da-v35/strings.xml
new file mode 100644
index 000000000..9401dbbe7
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-da-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privat rum"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Konfigurer et privat rum m.m."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privat rum"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-da/strings.xml b/SafetyCenter/Resources/res/values-da/strings.xml
index 16df659b8..59d275320 100644
--- a/SafetyCenter/Resources/res/values-da/strings.xml
+++ b/SafetyCenter/Resources/res/values-da/strings.xml
@@ -24,7 +24,7 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Der er ingen oplysninger endnu"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"Enhedslås, skærmlås, låseskærm, adgangskode, pinkode, mønster"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Biometri"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"Fingeraftryk, finger, tilføj fingeraftryk, ansigtslås, ansigt"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"Fingeraftryk, finger, tilføj fingeraftryk, ansigtsoplåsning, ansigt"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Privatliv"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Kontrolpanel, tilladelser, styringselementer"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Privatlivspanel"</string>
diff --git a/SafetyCenter/Resources/res/values-de-v34/strings.xml b/SafetyCenter/Resources/res/values-de-v34/strings.xml
index 7d9310728..4289c14a0 100644
--- a/SafetyCenter/Resources/res/values-de-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-de-v34/strings.xml
@@ -24,13 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Änderungen bei der Weitergabe von Standortdaten"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Daten, Datenweitergabe, Aktualisierungen der Datenweitergabe, Aktualisierungen der Weitergabe von Standortdaten, Weitergabe"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Datenschutz bei Anzeigen"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Informationen anpassen, die Apps verwenden, um dir Werbung anzuzeigen"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"Anzeigen, Datenschutz bei Anzeigen, Privacy Sandbox, Werbethemen, von Apps vorgeschlagene Werbung, Analyse von Werbeanzeigen"</string>
- <!-- no translation found for advanced_title (6259362998269627310) -->
- <skip />
- <!-- no translation found for more_settings_title (9033454654010697185) -->
- <skip />
+ <string name="advanced_title" msgid="6259362998269627310">"Weitere Einstellungen"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"Mehr Sicherheit und Datenschutz"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, Benachrichtigungen und mehr"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informationen zu den Arbeitsrichtlinien"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-de-v35/strings.xml b/SafetyCenter/Resources/res/values-de-v35/strings.xml
new file mode 100644
index 000000000..22f254518
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-de-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privater Bereich"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Privaten Bereich einrichten und mehr"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privater Bereich"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-el-v34/strings.xml b/SafetyCenter/Resources/res/values-el-v34/strings.xml
index cf3976381..651f580eb 100644
--- a/SafetyCenter/Resources/res/values-el-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-el-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"υγεία, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Ενημερώσεις στην κοινοποίηση δεδομένων για την τοποθεσία"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"δεδομένα, κοινοποίηση δεδομένων, ενημερώσεις κοινοποίησης δεδομένων, ενημερώσεις κοινοποίησης δεδομένων για την τοποθεσία, κοινοποίηση"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Απόρρητο διαφημίσεων"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Προσαρμόστε τις πληροφορίες που χρησιμοποιούν οι εφαρμογές για την εμφάνιση των διαφημίσεών σας"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"διαφημίσεις, απόρρητο διαφημίσεων, πλαίσιο ιδιωτικότητας, θέματα διαφημίσεων, διαφημίσεις που προτείνονται από εφαρμογές, μέτρηση διαφημίσεων"</string>
<string name="advanced_title" msgid="6259362998269627310">"Άλλες ρυθμίσεις"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Περισσότερες ρυθμίσεις για την ασφάλεια και το απόρρητο"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Αυτόματη συμπλήρωση, ειδοποιήσεις κ.ά."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Πληροφορίες σχετικά με την πολιτική εργασίας"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-el-v35/strings.xml b/SafetyCenter/Resources/res/values-el-v35/strings.xml
new file mode 100644
index 000000000..5cea492f7
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-el-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Ιδιωτικός χώρος"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Ρύθμιση Ιδιωτικού χώρου κ.ά."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Ιδιωτικός χώρος"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rAU-v34/strings.xml b/SafetyCenter/Resources/res/values-en-rAU-v34/strings.xml
index d7f503f7c..af32d279d 100644
--- a/SafetyCenter/Resources/res/values-en-rAU-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rAU-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Data sharing updates for location"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ads privacy"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Customise info that apps use to show you ads"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement"</string>
<string name="advanced_title" msgid="6259362998269627310">"Other settings"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"More security &amp; privacy"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"More security and privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, notifications and more"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Your work policy info"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml
new file mode 100644
index 000000000..311c5ca42
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Private Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Set up Private Space, and more"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Private Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rCA-v34/strings.xml b/SafetyCenter/Resources/res/values-en-rCA-v34/strings.xml
index 11cf54414..05cc98e75 100644
--- a/SafetyCenter/Resources/res/values-en-rCA-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rCA-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Data sharing updates for location"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ad privacy"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Customize info apps use to show you ads"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement"</string>
<string name="advanced_title" msgid="6259362998269627310">"Other settings"</string>
<string name="more_settings_title" msgid="9033454654010697185">"More security and privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, notifications, and more"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Your work policy info"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml
new file mode 100644
index 000000000..e0c36a7a0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Private Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Setup Private Space, and more"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Private Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rGB-v34/strings.xml b/SafetyCenter/Resources/res/values-en-rGB-v34/strings.xml
index d7f503f7c..af32d279d 100644
--- a/SafetyCenter/Resources/res/values-en-rGB-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rGB-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Data sharing updates for location"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ads privacy"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Customise info that apps use to show you ads"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement"</string>
<string name="advanced_title" msgid="6259362998269627310">"Other settings"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"More security &amp; privacy"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"More security and privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, notifications and more"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Your work policy info"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml
new file mode 100644
index 000000000..311c5ca42
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Private Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Set up Private Space, and more"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Private Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rIN-v34/strings.xml b/SafetyCenter/Resources/res/values-en-rIN-v34/strings.xml
index d7f503f7c..af32d279d 100644
--- a/SafetyCenter/Resources/res/values-en-rIN-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rIN-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Data sharing updates for location"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ads privacy"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Customise info that apps use to show you ads"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement"</string>
<string name="advanced_title" msgid="6259362998269627310">"Other settings"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"More security &amp; privacy"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"More security and privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, notifications and more"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Your work policy info"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml
new file mode 100644
index 000000000..311c5ca42
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Private Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Set up Private Space, and more"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Private Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rXC-v34/strings.xml b/SafetyCenter/Resources/res/values-en-rXC-v34/strings.xml
index 28d4151ea..f408d1fdb 100644
--- a/SafetyCenter/Resources/res/values-en-rXC-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rXC-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎Health, Health Connect‎‏‎‎‏‎"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎Data sharing updates for location‎‏‎‎‏‎"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing‎‏‎‎‏‎"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎Ad privacy‎‏‎‎‏‎"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎Customize info apps use to show you ads‎‏‎‎‏‎"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‎‎ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement‎‏‎‎‏‎"</string>
<string name="advanced_title" msgid="6259362998269627310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎Other settings‎‏‎‎‏‎"</string>
<string name="more_settings_title" msgid="9033454654010697185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎More security &amp; privacy‎‏‎‎‏‎"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‎Autofill, notifications, and more‎‏‎‎‏‎"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‎Your work policy info‎‏‎‎‏‎"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml
new file mode 100644
index 000000000..ad86de92f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎Private Space‎‏‎‎‏‎"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎Setup Private Space, and more‎‏‎‎‏‎"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎Private Space‎‏‎‎‏‎"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-es-rUS-v34/strings.xml b/SafetyCenter/Resources/res/values-es-rUS-v34/strings.xml
index 2bfbc6ed7..4158efa92 100644
--- a/SafetyCenter/Resources/res/values-es-rUS-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-es-rUS-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Actualizaciones del uso compartido de los datos de ubicación"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datos, uso compartido de los datos, actualizaciones del uso compartido de los datos, actualizaciones del uso compartido de los datos de ubicación, uso compartido"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidad en los anuncios"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personaliza la información que usan las apps para mostrarte anuncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anuncios, privacidad en los anuncios, privacy sandbox, temas de anuncios, anuncios sugeridos por apps, medición de anuncios"</string>
<string name="advanced_title" msgid="6259362998269627310">"Otras opciones"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mayor seguridad y privacidad"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autocompletar, notificaciones y más"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Información sobre la política de tu trabajo"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml b/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml
new file mode 100644
index 000000000..323af67b1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espacio privado"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configura el Espacio privado y mucho más"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espacio privado"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-es-v34/strings.xml b/SafetyCenter/Resources/res/values-es-v34/strings.xml
index 1a087e2e6..d03b74605 100644
--- a/SafetyCenter/Resources/res/values-es-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-es-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Salud, Salud conectada"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Cambios en los datos compartidos de ubicación"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datos, compartir datos, cambios en los datos que se comparten, cambios en los datos compartidos de ubicación, compartir"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidad en la publicidad"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personaliza la información que usan las aplicaciones para mostrarte anuncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anuncios, privacidad en la publicidad, Privacy Sandbox, temas de anuncios, anuncios sugeridos por aplicaciones, medición de anuncios"</string>
<string name="advanced_title" msgid="6259362998269627310">"Otros ajustes"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Más seguridad y privacidad"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autocompletar, notificaciones y más"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Información sobre la política de tu trabajo"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-es-v35/strings.xml b/SafetyCenter/Resources/res/values-es-v35/strings.xml
new file mode 100644
index 000000000..9901be878
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-es-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espacio privado"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configura el espacio privado y más"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espacio privado"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-et-v34/strings.xml b/SafetyCenter/Resources/res/values-et-v34/strings.xml
index 6e9d06cc2..914dcc54b 100644
--- a/SafetyCenter/Resources/res/values-et-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-et-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Tervis, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Andmete jagamise värskendused asukoha kohta"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Andmed, andmete jagamine, andmete jagamise värskendused, andmete jagamise värskendused asukoha kohta, jagamine"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Reklaamide privaatsus"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Kohandage teavet, mida rakendused kasutavad teile reklaamide näitamiseks"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklaamid, reklaamide privaatsus, privaatsuse liivakast, reklaamiteemad, rakenduse soovitatud reklaamid, reklaamide mõõtmine"</string>
<string name="advanced_title" msgid="6259362998269627310">"Muud seaded"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"Rohkem turvalisust ja privaatsust"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"Rohkem turvalisuse ja privaatsuse kohta"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automaattäide, märguanded jm"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Teie töökoha eeskirjade teave"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-et-v35/strings.xml b/SafetyCenter/Resources/res/values-et-v35/strings.xml
new file mode 100644
index 000000000..e2f169a10
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-et-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privaatne ruum"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Privaatse ruumi seadistamine ja muu"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privaatne ruum"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-eu-v34/strings.xml b/SafetyCenter/Resources/res/values-eu-v34/strings.xml
index 3785ce577..dae0daaab 100644
--- a/SafetyCenter/Resources/res/values-eu-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-eu-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Osasuna, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Kokapen-datuak partekatzeko moduaren inguruko berritasunak"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datuak, datuak partekatzea, datuak partekatzeko moduaren inguruko berritasunak, kokapen-datuak partekatzeko moduaren inguruko berritasunak, partekatzea"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Iragarkien pribatutasuna"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Pertsonalizatu aplikazioek iragarkiak erakusteko erabiltzen duten informazioa"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"iragarkiak, iragarkien pribatutasuna, privacy sandbox-a, iragarkien gaiak, aplikazioek iradokitako iragarkiak, iragarkien neurketa"</string>
<string name="advanced_title" msgid="6259362998269627310">"Beste ezarpen batzuk"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Segurtasun eta pribatutasun gehiago"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Betetze automatikoa, jakinarazpenak eta abar"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Laneko gidalerroei buruzko informazioa"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-eu-v35/strings.xml b/SafetyCenter/Resources/res/values-eu-v35/strings.xml
new file mode 100644
index 000000000..c22f585ab
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-eu-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Eremu pribatua"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Konfiguratu eremu pribatua eta abar"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Eremu pribatua"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fa-v34/strings.xml b/SafetyCenter/Resources/res/values-fa-v34/strings.xml
index 618c7f5f3..d8bf2b762 100644
--- a/SafetyCenter/Resources/res/values-fa-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-fa-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"‏سلامت، Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"به‌روزرسانی‌های هم‌رسانی داده برای مکان"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"داده، هم‌رسانی داده، به‌روزرسانی‌های هم‌رسانی داده، به‌روزرسانی‌های هم‌رسانی داده مکان، هم‌رسانی"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"حریم خصوصی آگهی"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"سفارشی‌سازی اطلاعات مورداستفاده برنامه‌ها برای نمایش آگهی به شما"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"آگهی‌ها، حریم خصوصی آگهی، جعبه ایمنی حریم خصوصی، موضوع آگهی‌ها، آگهی‌های پیشنهادی برنامه، سنجش آگهی"</string>
<string name="advanced_title" msgid="6259362998269627310">"تنظیمات دیگر"</string>
<string name="more_settings_title" msgid="9033454654010697185">"امنیت و حریم خصوصی بیشتر"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"تکمیل خودکار، اعلان‌ها، و موارد دیگر"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"اطلاعات خط‌مشی کاری شما"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-fa-v35/strings.xml b/SafetyCenter/Resources/res/values-fa-v35/strings.xml
new file mode 100644
index 000000000..a3eb194ee
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fa-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"فضای خصوصی"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"راه‌اندازی «فضای خصوصی»، و موارد دیگر"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"فضای خصوصی"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fi-v34/strings.xml b/SafetyCenter/Resources/res/values-fi-v34/strings.xml
index 71ef63fe1..3b0f8300b 100644
--- a/SafetyCenter/Resources/res/values-fi-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-fi-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Terveys, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Sijaintidatan jakamisen päivitykset"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, datan jakaminen, datan jakamisen päivitykset, sijaintidatan jakamisen päivitykset, jakaminen"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Mainosyksityisyys"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Muuta tietoja, joiden perusteella sovellukset näyttävät sinulle mainoksia"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"mainokset, mainosyksityisyys, privacy sandbox, mainosaiheet, sovellusten ehdottamat mainokset, mainosten mittaus"</string>
<string name="advanced_title" msgid="6259362998269627310">"Muut asetukset"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Lisää tietoturva‑ ja yksityisyysasetuksia"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automaattinen täyttö, ilmoitukset ja muuta"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Työkäytäntötietosi"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-fi-v35/strings.xml b/SafetyCenter/Resources/res/values-fi-v35/strings.xml
new file mode 100644
index 000000000..c80c17207
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fi-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Yksityinen tila"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Ota esimerkiksi yksityinen tila käyttöön"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Yksityinen tila"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-rCA-v34/strings.xml b/SafetyCenter/Resources/res/values-fr-rCA-v34/strings.xml
index 3097bb762..f1a8ad068 100644
--- a/SafetyCenter/Resources/res/values-fr-rCA-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-fr-rCA-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Santé, Connexion Santé"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Mises à jour des pratiques de partage des données pour la localisation"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Données, Partage des données, Mises à jour du partage des données, Mises à jour du partage des données pour la localisation, partage"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Confidentialité des annonces"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personnalisez les renseignements utilisés par les applications pour vous montrer des annonces"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annonces, confidentialité de l\'annonce, bac à sable de confidentialité, sujet de l\'annonce, annonces suggérées par les applications, mesure de l\'annonce"</string>
<string name="advanced_title" msgid="6259362998269627310">"Autres paramètres"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Plus de paramètres de sécurité et de confidentialité"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Remplissage automatique, notifications, etc."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Infos sur votre politique de travail"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml b/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml
new file mode 100644
index 000000000..06d909df8
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espace privé"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configuration de l\'espace privé, et plus"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espace privé"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-rCA/strings.xml b/SafetyCenter/Resources/res/values-fr-rCA/strings.xml
index 1ae13ac4b..a835c7139 100644
--- a/SafetyCenter/Resources/res/values-fr-rCA/strings.xml
+++ b/SafetyCenter/Resources/res/values-fr-rCA/strings.xml
@@ -40,7 +40,7 @@
<string name="advanced_security_title" msgid="1126833338772188155">"Plus de paramètres de sécurité"</string>
<string name="advanced_security_summary" msgid="6172253327022425123">"Chiffrement, authentifiants et plus"</string>
<string name="advanced_security_search_terms" msgid="3350609555814362075"></string>
- <string name="advanced_privacy_title" msgid="1117725225706176643">"Plus de paramètres de sécurité"</string>
+ <string name="advanced_privacy_title" msgid="1117725225706176643">"Plus de paramètres de confidentialité"</string>
<string name="advanced_privacy_summary" msgid="2281203390575069543">"Remplissage automatique, commandes d\'activité et plus"</string>
<string name="advanced_privacy_search_terms" msgid="5044404599789175222"></string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-v34/strings.xml b/SafetyCenter/Resources/res/values-fr-v34/strings.xml
index f4f320e94..92af5db49 100644
--- a/SafetyCenter/Resources/res/values-fr-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-fr-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Santé, Santé Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Mises à jour du partage des données pour la localisation"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Données, partage de données, mises à jour du partage des données, mises à jour du partage des données pour la localisation, partage"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Confidentialité des annonces"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personnalisez les infos qu\'utilisent les applis pour vous proposer des annonces"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annonces, confidentialité des annonces, Privacy Sandbox, thèmes d\'annonces, annonces suggérées par les applis, mesure des performances des annonces"</string>
<string name="advanced_title" msgid="6259362998269627310">"Autres paramètres"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Sécurité et confidentialité renforcées"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Saisie automatique, notifications et plus"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Infos sur vos règles professionnelles"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-fr-v35/strings.xml b/SafetyCenter/Resources/res/values-fr-v35/strings.xml
new file mode 100644
index 000000000..a1ba13767
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-fr-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espace privé"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configurez votre espace privé et bien plus"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espace privé"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-gl-v34/strings.xml b/SafetyCenter/Resources/res/values-gl-v34/strings.xml
index cdb2fd71f..16f9f9781 100644
--- a/SafetyCenter/Resources/res/values-gl-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-gl-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Saúde, Saúde conectada"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Actualizacións do uso compartido de datos de localización"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"datos, uso compartido de datos, actualizacións do uso compartido de datos, actualizacións do uso compartido de datos de localización, uso compartido"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidade dos anuncios"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personaliza a información que usan as aplicacións para mostrarche anuncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anuncios, privacidade nos anuncios, privacy sandbox, temas dos anuncios, anuncios suxeridos polas aplicacións, medición de anuncios"</string>
<string name="advanced_title" msgid="6259362998269627310">"Outras opcións de configuración"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Máis seguranza e privacidade"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autocompletar, notificacións e outras opcións"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Información sobre a túa política do traballo"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-gl-v35/strings.xml b/SafetyCenter/Resources/res/values-gl-v35/strings.xml
new file mode 100644
index 000000000..52586da18
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-gl-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espazo privado"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configura o espazo privado e moito máis"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espazo privado"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-gu-v34/strings.xml b/SafetyCenter/Resources/res/values-gu-v34/strings.xml
index 62f1adeda..0517fad28 100644
--- a/SafetyCenter/Resources/res/values-gu-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-gu-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"આરોગ્ય, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"લોકેશન માટે ડેટા શેરિંગ સંબંધિત અપડેટ"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ડેટા, ડેટા શેરિંગ, ડેટા શેરિંગ સંબંધિત અપડેટ, લોકેશન માટે ડેટા શેરિંગ સંબંધિત અપડેટ, શેરિંગ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"જાહેરાત સંબંધિત પ્રાઇવસી"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"તમને જાહેરાતો બતાવવા માટે ઍપ દ્વારા ઉપયોગમાં લેવાતી માહિતી કસ્ટમાઇઝ કરો"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"જાહેરાતો, જાહેરાત સંબંધિત પ્રાઇવસી, પ્રાઇવસી સૅન્ડબૉક્સ, જાહેરાતના વિષયો, ઍપ દ્વારા સૂચવેલી જાહેરાતો, જાહેરાતની માપણી"</string>
<string name="advanced_title" msgid="6259362998269627310">"અન્ય સેટિંગ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"વધુ સુરક્ષા અને પ્રાઇવસી"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ઑટોમૅટિક રીતે ભરવાની સુવિધા, નોટિફિકેશન અને બીજું ઘણું"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"તમારી ઑફિસની પૉલિસીની માહિતી"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-gu-v35/strings.xml b/SafetyCenter/Resources/res/values-gu-v35/strings.xml
new file mode 100644
index 000000000..23dfe440a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-gu-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ખાનગી સ્પેસ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ખાનગી સ્પેસનું સેટઅપ કરો અને બીજું ઘણું કરો"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ખાનગી સ્પેસ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hi-v34/strings.xml b/SafetyCenter/Resources/res/values-hi-v34/strings.xml
index 6dd399b93..3a941dc97 100644
--- a/SafetyCenter/Resources/res/values-hi-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-hi-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"जगह की जानकारी शेयर करने के तरीके के बारे में अपडेट"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"डेटा, डेटा शेयर करना, डेटा शेयर करने के अपडेट, जगह की जानकारी शेयर करने के बारे में अपडेट, शेयर करना"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"विज्ञापन देखने वाले की निजता बनाए रखने की सुविधा"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"अपने हिसाब से यह तय करें कि ऐप्लिकेशन आपको विज्ञापन दिखाने के लिए, कौनसी जानकारी का इस्तेमाल कर सकते हैं"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"विज्ञापन, विज्ञापन देखने वाले की निजता बनाए रखना, प्राइवसी सैंडबॉक्स, विज्ञापन का विषय, ऐप्लिकेशन के सुझाए गए विज्ञापन, और विज्ञापन की परफ़ॉर्मेंस का आकलन करना"</string>
<string name="advanced_title" msgid="6259362998269627310">"बेहतर सेटिंग"</string>
<string name="more_settings_title" msgid="9033454654010697185">"सुरक्षा और निजता की ज़्यादा सेटिंग"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ऑटोमैटिक भरना, सूचनाएं वगैरह"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"आपके ऑफ़िस की नीति के बारे में जानकारी"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-hi-v35/strings.xml b/SafetyCenter/Resources/res/values-hi-v35/strings.xml
new file mode 100644
index 000000000..ca4b78965
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hi-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"प्राइवेट स्पेस"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"प्राइवेट स्पेस सेटअप करें और अन्य काम करें"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"प्राइवेट स्पेस"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hr-v34/strings.xml b/SafetyCenter/Resources/res/values-hr-v34/strings.xml
index cf938415d..ef467b89b 100644
--- a/SafetyCenter/Resources/res/values-hr-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-hr-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Zdravlje, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Ažuriranja o dijeljenju podataka za lokaciju"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"podaci, dijeljenje podataka, ažuriranja dijeljenja podataka, ažuriranja dijeljenja podataka za lokaciju, dijeljenje"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Zaštita privatnosti u online oglašavanju"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Prilagodite podatke koje aplikacije koriste da bi vam prikazivale oglase"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"oglasi, zaštita privatnosti u online oglašavanju, privacy sandbox, teme oglasa, oglasi koje predlažu aplikacije, mjerenje oglasa"</string>
<string name="advanced_title" msgid="6259362998269627310">"Druge postavke"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Više sigurnosti i privatnosti"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatsko popunjavanje, obavijesti i drugo"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informacije o pravilima za poslovne uređaje"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-hr-v35/strings.xml b/SafetyCenter/Resources/res/values-hr-v35/strings.xml
new file mode 100644
index 000000000..024be31b1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hr-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privatni prostor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Postavljanje privatnog prostora i drugo"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privatni prostor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hr/strings.xml b/SafetyCenter/Resources/res/values-hr/strings.xml
index a4c43add7..7306fcc76 100644
--- a/SafetyCenter/Resources/res/values-hr/strings.xml
+++ b/SafetyCenter/Resources/res/values-hr/strings.xml
@@ -22,16 +22,16 @@
<string name="lock_screen_sources_summary" msgid="7220439741282516496"></string>
<string name="lock_screen_title" msgid="4069104894527169877">"Zaključavanje zaslona"</string>
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Još nema podataka"</string>
- <string name="lock_screen_search_terms" msgid="2678486357779794826">"Zaključavanje uređaja, zaključavanje zaslona, zaključan zaslon, zaključani zaslon, zaporka, PIN, uzorak"</string>
+ <string name="lock_screen_search_terms" msgid="2678486357779794826">"Zaključavanje uređaja, zaključavanje zaslona, zaključani zaslon, zaključani zaslon, zaporka, PIN, uzorak"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Biometrijski podaci"</string>
<string name="biometrics_search_terms" msgid="6040319118762671981">"Otisak prsta, prst, dodavanje otiska prsta, otključavanje licem, lice"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Privatnost"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Nadzorna ploča, dopuštenja, kontrole"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Nadzorna ploča za privatnost"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Prikaži aplikacije koje su nedavno upotrebljavale dopuštenja"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Pregledajte aplikacije koje su nedavno upotrebljavale dopuštenja"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Privatnost, nadzorna ploča za privatnost"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Upravitelj dopuštenja"</string>
- <string name="permission_manager_summary" msgid="8099852107340970790">"Upravljajte pristupom aplikacija svojim podacima"</string>
+ <string name="permission_manager_summary" msgid="8099852107340970790">"Upravljajte kojim podacima mogu pristupati vaše aplikacije"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Dopuštenja, upravitelj dopuštenja"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Kontrole privatnosti"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Kontroliranje pristupanja uređaja mikrofonu, kameri i ostalome"</string>
diff --git a/SafetyCenter/Resources/res/values-hu-v34/strings.xml b/SafetyCenter/Resources/res/values-hu-v34/strings.xml
index a228b2d8f..811e192cb 100644
--- a/SafetyCenter/Resources/res/values-hu-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-hu-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Egészség, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"A helyadatok megosztását érintő frissítések"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Adatok, adatmegosztás, adatmegosztási változások, helyadatokat érintő adatmegosztási változások, megosztás"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Hirdetésekhez kapcsolódó adatvédelem"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Személyre szabhatja azokat az információkat, amelyeket az alkalmazások arra használnak, hogy hirdetéseket jelenítsenek meg Önnek"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"hirdetések, hirdetésekhez kapcsolódó adatvédelem, privacy sandbox, hirdetéstéma, alkalmazások által javasolt hirdetések, hirdetésmérés"</string>
<string name="advanced_title" msgid="6259362998269627310">"Egyéb beállítások"</string>
<string name="more_settings_title" msgid="9033454654010697185">"További biztonsági és adatvédelmi beállítások"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatikus kitöltés, értesítések és egyebek"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Munkahelyi házirendekkel kapcsolatos adatok"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-hu-v35/strings.xml b/SafetyCenter/Resources/res/values-hu-v35/strings.xml
new file mode 100644
index 000000000..0fe083899
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hu-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privát terület"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Privát terület beállítása és egyebek"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privát terület"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-hy-v34/strings.xml b/SafetyCenter/Resources/res/values-hy-v34/strings.xml
index 3c126a203..158cec7c0 100644
--- a/SafetyCenter/Resources/res/values-hy-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-hy-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Տեղադրության մասին տվյալներով կիսվելու թույլտվության թարմացում"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Տվյալներ, Տվյալների փոխանցում, Տվյալներով կիսվելու եղանակի փոփոխություն, Տեղադրության մասին տվյալներով կիսվելու թույլտվության թարմացում, փոխանցում"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Գովազդի գաղտնիություն"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Անհատականացված տեղեկություններ, որոնք հավելվածներն օգտագործում են՝ ձեզ գովազդ ցուցադրելու համար"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"գովազդներ, գովազդի գաղտնիություն, privacy sandbox, գովազդի թեմաներ, հավելվածների կողմից առաջարկվող գովազդներ, գովազդի արդյունավետության գնահատում"</string>
<string name="advanced_title" msgid="6259362998269627310">"Այլ կարգավորումներ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Անվտանգության և գաղտնիության լրացուցիչ կարգավորումներ"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Ինքնալրացում, ծանուցումներ և ավելին"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Տեղեկություններ աշխատանքային կանոնների մասին"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-hy-v35/strings.xml b/SafetyCenter/Resources/res/values-hy-v35/strings.xml
new file mode 100644
index 000000000..54487ffa8
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-hy-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Անձնական տարածք"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Կարգավորեք անձնական տարածքը և ավելին"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Անձնական տարածք"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-in-v34/strings.xml b/SafetyCenter/Resources/res/values-in-v34/strings.xml
index bbb8aa1ae..9d375e022 100644
--- a/SafetyCenter/Resources/res/values-in-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-in-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Pembaruan berbagi data untuk lokasi"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Berbagi data, Pembaruan berbagi data, Pembaruan berbagi data untuk lokasi, berbagi"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privasi iklan"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Sesuaikan info yang digunakan aplikasi untuk menampilkan iklan kepada Anda"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"iklan, privasi iklan, privacy sandbox, topik iklan, iklan yang disarankan aplikasi, pengukuran iklan"</string>
<string name="advanced_title" msgid="6259362998269627310">"Setelan lainnya"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Keamanan &amp; privasi lainnya"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Isi otomatis, notifikasi, dan lainnya"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Info kebijakan profil kerja Anda"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-in-v35/strings.xml b/SafetyCenter/Resources/res/values-in-v35/strings.xml
new file mode 100644
index 000000000..2e2554992
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-in-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Ruang Pribadi"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Menyiapkan Ruang Pribadi, dan lainnya"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Ruang Pribadi"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-in/strings.xml b/SafetyCenter/Resources/res/values-in/strings.xml
index 4c3c2109b..d5579aa32 100644
--- a/SafetyCenter/Resources/res/values-in/strings.xml
+++ b/SafetyCenter/Resources/res/values-in/strings.xml
@@ -28,10 +28,10 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"Privasi"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Dasbor, izin, kontrol"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Dasbor privasi"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Menampilkan aplikasi yang baru-baru ini menggunakan izin"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Tampilkan aplikasi yang baru-baru ini menggunakan izin"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Privasi, Dasbor privasi"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Pengelola izin"</string>
- <string name="permission_manager_summary" msgid="8099852107340970790">"Mengontrol akses aplikasi ke data Anda"</string>
+ <string name="permission_manager_summary" msgid="8099852107340970790">"Kontrol akses aplikasi ke data Anda"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Izin, Pengelola izin"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Kontrol privasi"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Kontrol akses perangkat ke mikrofon, kamera, dan lainnya"</string>
diff --git a/SafetyCenter/Resources/res/values-is-v34/strings.xml b/SafetyCenter/Resources/res/values-is-v34/strings.xml
index 6eb83bf7d..6533a7ac3 100644
--- a/SafetyCenter/Resources/res/values-is-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-is-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Heilsa, Heilsutenging"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Uppfærslur um gagnadeilingu varðandi staðsetningu"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Gögn, gagnadeiling, uppfærslur á gagnadeilingu, uppfærslur á gagnadeilingu varðandi staðsetningu, deiling"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Persónuvernd auglýsinga"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Sérsníddu hvaða upplýsingar forrit nota til að birta þér auglýsingar"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"auglýsingar, persónuvernd auglýsinga, privacy sandbox, efni auglýsinga, auglýsingatillögur forrita, auglýsingamælingar"</string>
<string name="advanced_title" msgid="6259362998269627310">"Aðrar stillingar"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Aukið öryggi og persónuvernd"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Sjálfvirk útfylling, tilkynningar og fleira"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Upplýsingar um vinnureglurnar þínar"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-is-v35/strings.xml b/SafetyCenter/Resources/res/values-is-v35/strings.xml
new file mode 100644
index 000000000..d74f29e63
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-is-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Einkarými"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Setja upp einkarými og fleira"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Einkarými"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-it-v34/strings.xml b/SafetyCenter/Resources/res/values-it-v34/strings.xml
index fdc8d1cd9..ffbb82c41 100644
--- a/SafetyCenter/Resources/res/values-it-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-it-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Salute, Connessione Salute"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Aggiornamenti alla condivisione dei dati per la posizione"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dati, Condivisione dei dati, Aggiornamenti alla condivisione dei dati, Aggiornamenti alla condivisione dei dati per la posizione, Condivisione"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacy per gli annunci"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalizza le informazioni usate dalle app per mostrarti annunci"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annunci, privacy per gli annunci, privacy sandbox, argomenti degli annunci, annunci suggeriti dalle app, misurazione degli annunci"</string>
<string name="advanced_title" msgid="6259362998269627310">"Altre impostazioni"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Più sicurezza e privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Compilazione automatica, notifiche e altro ancora"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informazioni sulle norme di lavoro"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-it-v35/strings.xml b/SafetyCenter/Resources/res/values-it-v35/strings.xml
new file mode 100644
index 000000000..26df4d265
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-it-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Spazio privato"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configura lo Spazio privato e altro ancora"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Spazio privato"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-it/strings.xml b/SafetyCenter/Resources/res/values-it/strings.xml
index b3ff1668c..02f431a9a 100644
--- a/SafetyCenter/Resources/res/values-it/strings.xml
+++ b/SafetyCenter/Resources/res/values-it/strings.xml
@@ -24,7 +24,7 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Ancora nessuna informazione"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"Blocco dispositivo, Blocco schermo, Schermata di blocco, Password, PIN, Sequenza"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Dati biometrici"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"Impronta, Dito, Aggiungi impronta, Sblocco con il volto, Volto"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"Impronta, Dito, Aggiungi impronta, Sblocco con il Volto, Volto"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Privacy"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Dashboard, autorizzazioni, impostazioni"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Dashboard della privacy"</string>
diff --git a/SafetyCenter/Resources/res/values-iw-v34/strings.xml b/SafetyCenter/Resources/res/values-iw-v34/strings.xml
index 245ca91bf..43296d1bf 100644
--- a/SafetyCenter/Resources/res/values-iw-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-iw-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"‏בריאות, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"עדכונים לגבי שיתוף נתונים עבור המיקום"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"נתונים, שיתוף נתונים, עדכונים לגבי שיתוף נתונים, עדכונים לגבי שיתוף נתונים עבור המיקום, שיתוף"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"פרטיות בפרסום"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"התאמה אישית של המידע שאפליקציות משתמשות בו כדי להציג לך מודעות"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"מודעות, פרטיות בפרסום, ארגז חול לפרטיות, נושאי מודעות, מודעות שאפליקציות מציעות, מדידת מודעות"</string>
<string name="advanced_title" msgid="6259362998269627310">"הגדרות אחרות"</string>
<string name="more_settings_title" msgid="9033454654010697185">"עוד אבטחה ופרטיות"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"מילוי אוטומטי, התראות ועוד"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"פרטי המדיניות של מקום העבודה"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-iw-v35/strings.xml b/SafetyCenter/Resources/res/values-iw-v35/strings.xml
new file mode 100644
index 000000000..edb3e2862
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-iw-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"מרחב פרטי"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"הגדרת מרחב פרטי ועוד"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"מרחב פרטי"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ja-v34/strings.xml b/SafetyCenter/Resources/res/values-ja-v34/strings.xml
index 7bdb04e1c..8a49d1667 100644
--- a/SafetyCenter/Resources/res/values-ja-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ja-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ヘルス, ヘルス コネクト"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"位置情報を共有する方法の更新"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"データ, データ 共有, データ 共有 更新, データ 共有 更新 位置情報, 共有"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"広告のプライバシー"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"広告を表示するためにアプリが使用する情報をカスタマイズします"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"広告, 広告のプライバシー, プライバシー サンドボックス, 広告 トピック, アプリによる広告の提案, 広告 測定"</string>
<string name="advanced_title" msgid="6259362998269627310">"その他の設定"</string>
<string name="more_settings_title" msgid="9033454654010697185">"その他のセキュリティとプライバシー"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"自動入力、通知など"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"仕事用ポリシーに関する情報"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ja-v35/strings.xml b/SafetyCenter/Resources/res/values-ja-v35/strings.xml
new file mode 100644
index 000000000..4bd389ee3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ja-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"プライベート スペース"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"プライベート スペースの設定、その他"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"プライベート スペース"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ka-v34/strings.xml b/SafetyCenter/Resources/res/values-ka-v34/strings.xml
index d84af11e4..97e2afc2d 100644
--- a/SafetyCenter/Resources/res/values-ka-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ka-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"მონაცემების გაზიარების განახლებები მდებარეობისთვის"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"მონაცემები, მონაცემების გაზიარება, მონაცემების გაზიარების განახლებები, მონაცემების გაზიარების განახლებები მდებარეობისთვის, გაზიარება"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"რეკლამის კონფიდენციალურობა"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ინფორმაციის მორგება, რომელსაც აპები იყენებს თქვენთვის რეკლამის საჩვენებლად"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"რეკლამები, რეკლამის კონფიდენციალურობა, privacy sandbox, სარეკლამო თემა, აპის შემოთავაზებული რეკლამები, რეკლამის გაზომვა"</string>
<string name="advanced_title" msgid="6259362998269627310">"სხვა პარამეტრები"</string>
<string name="more_settings_title" msgid="9033454654010697185">"მეტი უსაფრთხოება და კონფიდენციალურობა"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ავტომატური შევსება, შეტყობინებები, და სხვა"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ინფორმაცია თქვენი სამსახურის წესების შესახებ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ka-v35/strings.xml b/SafetyCenter/Resources/res/values-ka-v35/strings.xml
new file mode 100644
index 000000000..480f7e83c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ka-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"პირადი სივრცე"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"დააყენეთ პირადი სივრცე და ა.შ."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"პირადი სივრცე"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-kk-v34/strings.xml b/SafetyCenter/Resources/res/values-kk-v34/strings.xml
index ac7746d7e..1efaa3f6b 100644
--- a/SafetyCenter/Resources/res/values-kk-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-kk-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Денсаулық, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Локация деректерін бөлісу жаңартулары"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Деректер, Деректерді бөлісу, Деректерді бөлісу жаңартулары, Локация деректерін бөлісу жаңартулары"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Жарнама құпиялығы"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Қолданбалардың сізге жарнама көрсету үшін пайдаланатын ақпаратын реттеңіз."</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"жарнамалар, жарнамадағы құпиялық, privacy sandbox, жарнама тақырыптары, қолданба ұсынған жарнамалар, жарнама көрсеткіштерін өлшеу"</string>
<string name="advanced_title" msgid="6259362998269627310">"Басқа параметрлер"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Күшейтілген қауіпсіздік пен құпиялық"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автотолтыру, хабарландырулар және тағы басқалар"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Жұмыс саясатыңыз туралы ақпарат"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-kk-v35/strings.xml b/SafetyCenter/Resources/res/values-kk-v35/strings.xml
new file mode 100644
index 000000000..f01ade9b8
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-kk-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Жеке бөлме"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Жеке бөлмені реттеу және т.б."</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Жеке бөлме"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-kk/strings.xml b/SafetyCenter/Resources/res/values-kk/strings.xml
index 2d8a6ee6a..79b5204fa 100644
--- a/SafetyCenter/Resources/res/values-kk/strings.xml
+++ b/SafetyCenter/Resources/res/values-kk/strings.xml
@@ -28,7 +28,7 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"Құпиялық"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Басқару тақтасы, рұқсаттар, басқару элементтері"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Құпиялық тақтасы"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Жақында рұқсаттарды пайдаланған қолданбаларды көрсетеді."</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Жақында рұқсаттарды пайдаланған қолданбаларды көрсету"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Құпиялық, құпиялық тақтасы"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Рұқсат менеджері"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Қолданбалардың деректерді пайдалану рұқсатын басқару"</string>
diff --git a/SafetyCenter/Resources/res/values-km-v34/strings.xml b/SafetyCenter/Resources/res/values-km-v34/strings.xml
index e9dd1fe35..df7009b2e 100644
--- a/SafetyCenter/Resources/res/values-km-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-km-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"សុខភាព Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ការធ្វើបច្ចុប្បន្នភាពការចែករំលែកទិន្នន័យសម្រាប់ទីតាំង"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ទិន្នន័យ ការចែករំលែកទិន្នន័យ បច្ចុប្បន្នភាពការចែករំលែកទិន្នន័យ បច្ចុប្បន្នភាពការចែករំលែកទិន្នន័យសម្រាប់ទីតាំង ការចែករំលែក"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ឯកជនភាពនៃការផ្សាយពាណិជ្ជកម្ម"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ប្ដូរការប្រើប្រាស់កម្មវិធីព័ត៌មានតាមបំណង ដើម្បីបង្ហាញការផ្សាយពាណិជ្ជកម្មដល់អ្នក"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ការផ្សាយពាណិជ្ជកម្ម, ឯកជនភាពនៃការផ្សាយពាណិជ្ជកម្ម, privacy sandbox, ប្រធានបទផ្សាយពាណិជ្ជកម្ម, ការផ្សាយពាណិជ្ជកម្មដែលណែនាំដោយកម្មវិធី, ការវាស់ស្ទង់ការផ្សាយពាណិជ្ជកម្ម"</string>
<string name="advanced_title" msgid="6259362998269627310">"ការកំណត់​ផ្សេងទៀត"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ឯកជនភាព និងសុវត្ថិភាពបន្ថែម"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"បំពេញស្វ័យប្រវត្តិ ការជូនដំណឹង និងច្រើនទៀត"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ព័ត៌មាន​អំពីគោលការណ៍ការងារ​របស់អ្នក"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-km-v35/strings.xml b/SafetyCenter/Resources/res/values-km-v35/strings.xml
new file mode 100644
index 000000000..094bcb095
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-km-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"បន្ទប់​ឯកជន"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"រៀបចំបន្ទប់ឯកជន និងធ្វើអ្វីៗជាច្រើនទៀត"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"បន្ទប់​ឯកជន"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-km/strings.xml b/SafetyCenter/Resources/res/values-km/strings.xml
index 898f533d1..be8b2369d 100644
--- a/SafetyCenter/Resources/res/values-km/strings.xml
+++ b/SafetyCenter/Resources/res/values-km/strings.xml
@@ -24,7 +24,7 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"មិន​ទាន់​មាន​ព័ត៌មាន​នៅ​ឡើយ​ទេ"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"ការចាក់សោឧបករណ៍, ការចាក់សោអេក្រង់, អេក្រង់ចាក់សោ, អេក្រង់ចាក់សោ, ពាក្យសម្ងាត់, កូដ​ PIN, លំនាំ"</string>
<string name="biometrics_title" msgid="5859504610285212938">"ជីវមាត្រ"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"ស្នាមម្រាមដៃ, ម្រាមដៃ, បញ្ចូលស្នាមម្រាមដៃ, ការដោះសោតាមទម្រង់មុខ, មុខ"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"ស្នាមម្រាមដៃ, ម្រាមដៃ, បញ្ចូលស្នាមម្រាមដៃ, ការដោះសោដោយស្កេនមុខ, មុខ"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"ឯកជនភាព"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"ផ្ទាំងគ្រប់គ្រង ការអនុញ្ញាត ការគ្រប់គ្រង"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"ផ្ទាំងគ្រប់គ្រង​ឯកជនភាព"</string>
diff --git a/SafetyCenter/Resources/res/values-kn-v34/strings.xml b/SafetyCenter/Resources/res/values-kn-v34/strings.xml
index 7df9bf60a..19dcdad15 100644
--- a/SafetyCenter/Resources/res/values-kn-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-kn-v34/strings.xml
@@ -17,18 +17,16 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="lock_screen_sources_title" msgid="5493678510117489865">"ಸಾಧನದ ಅನ್‌ಲಾಕ್"</string>
+ <string name="lock_screen_sources_title" msgid="5493678510117489865">"ಸಾಧನ ಅನ್‌ಲಾಕ್"</string>
<string name="biometrics_title_for_work" msgid="1842284049407771568">"ಕೆಲಸದ ಕುರಿತ ಬಯೋಮೆಟ್ರಿಕ್ಸ್"</string>
<string name="privacy_sources_summary" msgid="4083646673569677049">"ಅನುಮತಿಗಳು, ಡ್ಯಾಶ್‌ಬೋರ್ಡ್, ಕಂಟ್ರೋಲ್‌ಗಳು"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"ಆರೋಗ್ಯ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ಸ್ಥಳದ ಡೇಟಾ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ ಕುರಿತ ಅಪ್‌ಡೇಟ್‌ಗಳು"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ಡೇಟಾ, ಡೇಟಾ ಹಂಚಿಕೆ, ಡೇಟಾ ಹಂಚಿಕೆಯ ಅಪ್‌ಡೇಟ್‌ಗಳು, ಸ್ಥಳ ಹಂಚಿಕೆಗಾಗಿ ಡೇಟಾ ಹಂಚಿಕೆಯ ಅಪ್‌ಡೇಟ್‌ಗಳು"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ಜಾಹೀರಾತು ಗೌಪ್ಯತೆ"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ನಿಮಗೆ ಜಾಹೀರಾತುಗಳನ್ನು ತೋರಿಸಲು ಬಳಸುವ ಮಾಹಿತಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ಜಾಹೀರಾತುಗಳು, ಜಾಹೀರಾತು ಗೌಪ್ಯತೆ, ಪ್ರೈವೆಸಿ ಸ್ಯಾಂಡ್‌ಬಾಕ್ಸ್, ಆ್ಯಡ್ ವಿಷಯಗಳು, ಆ್ಯಪ್ ಶಿಫಾರಸು ಮಾಡಿದ ಜಾಹೀರಾತುಗಳು, ಜಾಹೀರಾತು ಮಾಪನ"</string>
<string name="advanced_title" msgid="6259362998269627310">"ಇತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ಇನ್ನಷ್ಟು ಭದ್ರತೆ ಮತ್ತು ಗೌಪ್ಯತೆ"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ಆಟೋಫಿಲ್, ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಇನ್ನಷ್ಟು"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ನಿಮ್ಮ ಉದ್ಯೋಗ ನೀತಿಯ ಮಾಹಿತಿ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-kn-v35/strings.xml b/SafetyCenter/Resources/res/values-kn-v35/strings.xml
new file mode 100644
index 000000000..5260029a7
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-kn-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ಖಾಸಗಿ ಸ್ಪೇಸ್"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಿ ಹಾಗೂ ಇನ್ನಷ್ಟನ್ನು ಮಾಡಿ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ಖಾಸಗಿ ಸ್ಪೇಸ್"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ko-v34/strings.xml b/SafetyCenter/Resources/res/values-ko-v34/strings.xml
index 85108406a..347b46bdb 100644
--- a/SafetyCenter/Resources/res/values-ko-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ko-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"건강, 헬스 커넥트"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"위치 데이터 공유 방법 업데이트"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"데이터, 데이터 공유, 데이터 공유 업데이트, 위치 관련 데이터 공유 업데이트, 공유"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"광고 개인 정보 보호"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"앱에서 광고 표시에 사용하는 정보를 맞춤설정합니다."</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"광고, 광고 개인 정보 보호, 개인 정보 보호 샌드박스, 광고 주제, 앱 추천 광고, 광고 측정"</string>
<string name="advanced_title" msgid="6259362998269627310">"기타 설정"</string>
<string name="more_settings_title" msgid="9033454654010697185">"보안 및 개인 정보 보호 더보기"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"자동 완성, 알림 등"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"직장 프로필 정책 정보"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ko-v35/strings.xml b/SafetyCenter/Resources/res/values-ko-v35/strings.xml
new file mode 100644
index 000000000..56fedb178
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ko-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"비공개 스페이스"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"비공개 스페이스 설정 등"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"비공개 스페이스"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ky-v34/strings.xml b/SafetyCenter/Resources/res/values-ky-v34/strings.xml
index cfd1f8ed2..9d4a1ede9 100644
--- a/SafetyCenter/Resources/res/values-ky-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ky-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Ден соолук, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Жүргөн жер тууралуу маалыматты бөлүшүү ыкмасын жаңыртуу"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Маалымат, маалыматты бөлүшүү, маалыматты бөлүшүү ыкмасын жаңыртуу, кайда жүргөнүмдү көрсөтүү функциясы үчүн маалыматты бөлүшүү ыкмасын жаңыртуу"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Жарнаманын купуялыгы"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Колдонмолор жарнамаларды кандай маалыматты негизинде көрсөтөрүн тандайсыз"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"жарнамалар, жарнаманын купуялыгы, privacy sandbox, жарнама темалары, колдонмолор сунуштаган жарнамалар, жарнаманы өлчөө"</string>
- <string name="advanced_title" msgid="6259362998269627310">"Башка жөндөөлөр"</string>
+ <string name="advanced_title" msgid="6259362998269627310">"Башка параметрлер"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Көбүрөөк коопсуздук жана купуялык"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автотолтуруу, билдирмелер жана башкалар"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Жумуш саясаты тууралуу маалымат"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ky-v35/strings.xml b/SafetyCenter/Resources/res/values-ky-v35/strings.xml
new file mode 100644
index 000000000..307c3a532
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ky-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Жеке чөйрө"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Жеке чөйрөнү тууралоо жана башка нерселер"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Жеке чөйрө"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lo-v34/strings.xml b/SafetyCenter/Resources/res/values-lo-v34/strings.xml
index a301cf8c0..fe18b3024 100644
--- a/SafetyCenter/Resources/res/values-lo-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-lo-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ສຸຂະພາບ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ການອັບເດດການແບ່ງປັນຂໍ້ມູນສະຖານທີ່"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ຂໍ້ມູນ, ການແບ່ງປັນຂໍ້ມູນ, ການອັບເດດການແບ່ງປັນຂໍ້ມູນ, ການອັບເດດການແບ່ງປັນຂໍ້ມູນສະຖານທີ່, ການແບ່ງປັນ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ຄວາມເປັນສ່ວນກ່ຽວກັບຕົວໂຄສະນາ"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ປັບແຕ່ງຂໍ້ມູນແອັບທີ່ໃຊ້ສະແດງໂຄສະນາໃຫ້ທ່ານເຫັນ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ໂຄສະນາ, ຄວາມເປັນສ່ວນຕົວກ່ຽວກັບຕົວໂຄສະນາ, Privacy Sandbox, ຫົວຂໍ້ໂຄສະນາ, ໂຄສະນາແນະນຳແອັບ, ການວັດແທກໂຄສະນາ"</string>
<string name="advanced_title" msgid="6259362998269627310">"ການຕັ້ງຄ່າອື່ນໆ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ຄວາມປອດໄພ ແລະ ຄວາມເປັນສ່ວນຕົວເພີ່ມເຕີມ"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ການຕື່ມຂໍ້ມູນອັດຕະໂນມັດ, ການແຈ້ງເຕືອນ ແລະ ອື່ນໆ"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ຂໍ້ມູນນະໂຍບາຍບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-lo-v35/strings.xml b/SafetyCenter/Resources/res/values-lo-v35/strings.xml
new file mode 100644
index 000000000..381410da3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lo-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ພື້ນທີ່ສ່ວນຕົວ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ຕັ້ງຄ່າພື້ນທີ່ສ່ວນຕົວ ແລະ ອື່ນໆ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ພື້ນທີ່ສ່ວນຕົວ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lt-v34/strings.xml b/SafetyCenter/Resources/res/values-lt-v34/strings.xml
index 844910cd8..ffe1d55e0 100644
--- a/SafetyCenter/Resources/res/values-lt-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-lt-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Sveikata, „Health Connect“"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Vietovės duomenų bendrinimo naujiniai"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Duomenys, duomenų bendrinimas, duomenų bendrinimo naujiniai, vietovės duomenų bendrinimo naujiniai, bendrinimas"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Su skelbimais susijęs privatumas"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Tinkinti informaciją, kurią programos naudoja skelbimams rodyti"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"skelbimai, su skelbimais susijęs privatumas, Privatumo „sandbox“ (smėlio dėžė), skelbimų temos, programų siūlomi skelbimai, skelbimų vertinimas"</string>
<string name="advanced_title" msgid="6259362998269627310">"Kiti nustatymai"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Geresnė sauga ir privatumas"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatinis pildymas, pranešimai ir kt."</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Darbo politikos informacija"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-lt-v35/strings.xml b/SafetyCenter/Resources/res/values-lt-v35/strings.xml
new file mode 100644
index 000000000..b18eda435
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lt-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privati erdvė"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Nustatykite privačią erdvę ir atlikite kitų veiksmų"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privati erdvė"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-lv-v34/strings.xml b/SafetyCenter/Resources/res/values-lv-v34/strings.xml
index 24753a3c8..b6f5238c2 100644
--- a/SafetyCenter/Resources/res/values-lv-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-lv-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Atjauninājumi atrašanās vietas datu kopīgošanā"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dati, datu kopīgošana, datu kopīgošanas atjauninājumi, atjauninājumi atrašanās vietas datu kopīgošanā, kopīgošana"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Reklāmu konfidencialitāte"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Pielāgojiet informāciju, ko lietotnes var izmantot, lai rādītu jums reklāmas"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklāmas, reklāmu konfidencialitāte, konfidencialitātes smilškaste, reklāmu tēmas, lietotņu ieteiktas reklāmas, reklāmu izvērtēšana"</string>
<string name="advanced_title" msgid="6259362998269627310">"Citi iestatījumi"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Citi drošības un konfidencialitātes iestatījumi"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automātiskā aizpilde, paziņojumi un citi iestatījumi"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informācija par jūsu darbavietas politiku"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-lv-v35/strings.xml b/SafetyCenter/Resources/res/values-lv-v35/strings.xml
new file mode 100644
index 000000000..ffb1a7f4b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-lv-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privātā mape"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Privātās mapes iestatīšana un citas iespējas"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privātā mape"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mk-v34/strings.xml b/SafetyCenter/Resources/res/values-mk-v34/strings.xml
index 93c7d5d49..b3c1db290 100644
--- a/SafetyCenter/Resources/res/values-mk-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-mk-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Здравје, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Промени во споделувањето на податоците за локација"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Податоци, споделување податоци, промени во споделувањето податоци, промени во споделувањето на податоците за локација, споделување"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Приватност за реклами"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Приспособете ги податоците што апликациите ги користат за да ви прикажуваат реклами"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"реклами, приватност за реклами, privacy sandbox, теми на реклами, реклами предложени од апликации, мерење реклами"</string>
<string name="advanced_title" msgid="6259362998269627310">"Други поставки"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"Повеќе безбедност и приватност"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"Дополнителни поставки"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автоматско пополнување, известувања и друго"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Податоци за работните правила"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-mk-v35/strings.xml b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
new file mode 100644
index 000000000..879a67555
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Приватен простор"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Поставување „Приватен простор“ и друго"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Приватен простор"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mk/strings.xml b/SafetyCenter/Resources/res/values-mk/strings.xml
index bc3dbfd9d..2b2414d0d 100644
--- a/SafetyCenter/Resources/res/values-mk/strings.xml
+++ b/SafetyCenter/Resources/res/values-mk/strings.xml
@@ -24,15 +24,15 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Сѐ уште нема податоци"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"Заклучување уред, Заклучување екран, Заклучен екран, Лозинка, PIN, Шема"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Биометрика"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"Отпечаток, Прст, Додај отпечаток, Отклучување со лик, Лице"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"Отпечаток, Прст, Додај отпечаток, Отклучување со лик, Лик"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Приватност"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Контролна табла, дозволи, контроли"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Контролна табла за приватност"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Прикажи кои апликации користеа дозволи неодамна"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Прикажува кои апликации користеле дозволи неодамна"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Приватност, Контролна табла за приватност"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"Управник со дозволи"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"Управувач со дозволи"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Го контролира пристапот на апликациите до вашите податоци"</string>
- <string name="permission_manager_search_terms" msgid="2895147613099694722">"Дозволи, Управник со дозволи"</string>
+ <string name="permission_manager_search_terms" msgid="2895147613099694722">"Дозволи, Управувач со дозволи"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Контроли за приватноста"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Го контролира пристапот на уредот до микрофонот, камерата и друго"</string>
<string name="privacy_controls_search_terms" msgid="3774472175934304165">"Приватност, Контроли на приватноста"</string>
diff --git a/SafetyCenter/Resources/res/values-ml-v34/strings.xml b/SafetyCenter/Resources/res/values-ml-v34/strings.xml
index 445cb0598..a53898e00 100644
--- a/SafetyCenter/Resources/res/values-ml-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ml-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ലൊക്കേഷൻ ഡാറ്റ പങ്കിടുന്നത് സംബന്ധിച്ച അപ്‌ഡേറ്റുകൾ"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ഡാറ്റ, ഡാറ്റ പങ്കിടൽ, ഡാറ്റ പങ്കിടൽ അപ്‌ഡേറ്റുകൾ, ലൊക്കേഷനുമായി ബന്ധപ്പെട്ട ഡാറ്റ പങ്കിടൽ അപ്ഡേറ്റുകൾ, പങ്കിടൽ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"പരസ്യവുമായി ബന്ധപ്പെട്ട സ്വകാര്യത"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"നിങ്ങളെ പരസ്യങ്ങൾ കാണിക്കുന്നതിന് ആപ്പുകൾ ഉപയോഗിക്കുന്ന വിവരങ്ങൾ ഇഷ്ടാനുസൃതമാക്കുക"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"പരസ്യങ്ങൾ, പരസ്യവുമായി ബന്ധപ്പെട്ട സ്വകാര്യത, സ്വകാര്യതാ സാൻഡ്ബോക്‌സ്, പരസ്യത്തിന്റെ വിഷയങ്ങൾ, ആപ്പ് നിർദ്ദേശിക്കുന്ന പരസ്യങ്ങൾ, ആഡ് മെഷർമെന്റ്"</string>
<string name="advanced_title" msgid="6259362998269627310">"മറ്റ് ക്രമീകരണം"</string>
<string name="more_settings_title" msgid="9033454654010697185">"കൂടുതൽ സുരക്ഷയും സ്വകാര്യതയും"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"സ്വയമേവ പൂരിപ്പിക്കൽ, അറിയിപ്പുകൾ എന്നിവയും മറ്റും"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"നിങ്ങളുടെ ഔദ്യോഗിക നയ വിവരങ്ങൾ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ml-v35/strings.xml b/SafetyCenter/Resources/res/values-ml-v35/strings.xml
new file mode 100644
index 000000000..c6e728c4f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ml-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"സ്വകാര്യ Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"സ്വകാര്യ Space സജ്ജീകരിക്കുകയും മറ്റും ചെയ്യൂ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"സ്വകാര്യ Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mn-v34/strings.xml b/SafetyCenter/Resources/res/values-mn-v34/strings.xml
index bb696e20e..2f498893b 100644
--- a/SafetyCenter/Resources/res/values-mn-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-mn-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Байршлын өгөгдөл хуваалцах шинэчлэлт"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Өгөгдөл, өгөгдөл хуваалцах, өгөгдөл хуваалцах шинэчлэлт, байршлын өгөгдөл хуваалцах шинэчлэлт, хуваалцах"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Зарын нууцлал"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Танд зар харуулахын тулд мэдээллийн аппуудын ашиглалтыг өөрчлөх"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"зар, зарын нууцлал, privacy sandbox, зарын сэдэв, аппын санал болгосон зар, зарын хэмжилт"</string>
<string name="advanced_title" msgid="6259362998269627310">"Бусад тохиргоо"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Бусад аюулгүй байдал, нууцлал"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автоматаар бөглөх хэсэг, мэдэгдэл болон бусад"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Таны ажлын бодлогын мэдээлэл"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-mn-v35/strings.xml b/SafetyCenter/Resources/res/values-mn-v35/strings.xml
new file mode 100644
index 000000000..290462d37
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mn-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Хувийн орон зай"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Хувийн орон зай тохируулах болон илүү ихийг хийх"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Хувийн орон зай"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-mr-v34/strings.xml b/SafetyCenter/Resources/res/values-mr-v34/strings.xml
index 60cb16f3c..f2d620adc 100644
--- a/SafetyCenter/Resources/res/values-mr-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-mr-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"स्थानासाठी डेटा शेअरिंगसंबंधित अपडेट"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"डेटा, डेटा शेअरिंग, डेटा शेअरिंगसंबंधित अपडेट, स्थानासाठी डेटा शेअरिंगसंबंधित अपडेट, शेअरिंग"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"जाहिरात गोपनीयता"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"तुम्‍हाला जाहिराती दाखवण्‍यासाठी ॲप्सनी कोणती माहिती वापरावी ते कस्टमाइझ करा"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"जाहिराती, जाहिरातीसंबंधित गोपनीयता, प्रायव्हसी सॅंडबाॅक्स, जाहिरातीचे विषय, अ‍ॅपने सुचवलेल्या जाहिराती, जाहिरातीशी संबंधित मापन"</string>
<string name="advanced_title" msgid="6259362998269627310">"इतर सेटिंग्ज"</string>
<string name="more_settings_title" msgid="9033454654010697185">"आणखी सुरक्षा आणि गोपनीयता"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ऑटोफिल, सूचना आणि आणखी बरेच काही"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"तुमच्या कामासंबंधित धोरणाची माहिती"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-mr-v35/strings.xml b/SafetyCenter/Resources/res/values-mr-v35/strings.xml
new file mode 100644
index 000000000..0ec596e1c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-mr-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"खाजगी स्पेस"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"खाजगी स्पेस आणि आणखी बरेच काही सेट करा"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"खाजगी स्पेस"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ms-v34/strings.xml b/SafetyCenter/Resources/res/values-ms-v34/strings.xml
index 101490bc0..68102f138 100644
--- a/SafetyCenter/Resources/res/values-ms-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ms-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Kemaskinian perkongsian data untuk lokasi"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Perkongsian data, Kemaskinian perkongsian data, Kemaskinian perkongsian data untuk lokasi, perkongsian"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privasi iklan"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Sesuaikan maklumat yang digunakan apl untuk menunjukkan iklan kepada anda"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"iklan, privasi iklan, kotak pasir privasi, topik iklan, iklan cadangan apl, ukuran iklan"</string>
<string name="advanced_title" msgid="6259362998269627310">"Tetapan lain"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"Lebih banyak sekuriti &amp; privasi"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"Lagi sekuriti &amp; privasi"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autolengkap, pemberitahuan dan banyak lagi"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Maklumat dasar kerja anda"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ms-v35/strings.xml b/SafetyCenter/Resources/res/values-ms-v35/strings.xml
new file mode 100644
index 000000000..b0694a876
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ms-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Ruang Peribadi"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Sediakan Ruang Peribadi dan pelbagai lagi"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Ruang Peribadi"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-my-v34/strings.xml b/SafetyCenter/Resources/res/values-my-v34/strings.xml
index 9415ecbd1..9b2b27707 100644
--- a/SafetyCenter/Resources/res/values-my-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-my-v34/strings.xml
@@ -17,18 +17,16 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="lock_screen_sources_title" msgid="5493678510117489865">"စက်ပစ္စည်းဖွင့်ခြင်း"</string>
+ <string name="lock_screen_sources_title" msgid="5493678510117489865">"စက်ပစ္စည်းလော့ခ်ဖွင့်ရန်"</string>
<string name="biometrics_title_for_work" msgid="1842284049407771568">"အလုပ်အတွက် ဇီဝမက်ထရစ် အချက်အလက်များ"</string>
- <string name="privacy_sources_summary" msgid="4083646673569677049">"ခွင့်ပြုချက်များ၊ ဒက်ရှ်ဘုတ်၊ သတ်မှတ်ချက်များ"</string>
+ <string name="privacy_sources_summary" msgid="4083646673569677049">"ခွင့်ပြုချက်များ၊ ဒက်ရှ်ဘုတ်၊ ထိန်းချုပ်မှုများ"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"ကျန်းမာရေး၊ Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"တည်နေရာအတွက် ဒေတာမျှဝေခြင်း အပ်ဒိတ်"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ဒေတာ၊ ဒေတာမျှဝေခြင်း၊ ဒေတာမျှဝေခြင်း အပ်ဒိတ်၊ တည်နေရာအတွက် ဒေတာမျှဝေခြင်း အပ်ဒိတ်၊ မျှဝေခြင်း"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ကြော်ငြာဆိုင်ရာ အချက်အလက်လုံခြုံမှု"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"အက်ပ်များက သင့်အား ကြော်ငြာများပြရန်သုံးသော အချက်အလက်ကို စိတ်ကြိုက်လုပ်နိုင်သည်"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ကြော်ငြာ၊ ကြော်ငြာဆိုင်ရာ အချက်အလက်လုံခြုံမှု၊ privacy sandbox၊ ကြော်ငြာအကြောင်းအရာ၊ အက်ပ်အကြံပြုကြော်ငြာ၊ ကြော်ငြာ တိုင်းတာအကဲဖြတ်မှု"</string>
<string name="advanced_title" msgid="6259362998269627310">"အခြား ဆက်တင်များ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"နောက်ထပ် လုံခြုံရေးနှင့် ကိုယ်ရေးဒေတာ လုံခြုံမှု"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"အော်တိုဖြည့်၊ အကြောင်းကြားချက်များစသည်"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"သင့်အလုပ်ခွင်မူဝါဒ အချက်အလက်"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-my-v35/strings.xml b/SafetyCenter/Resources/res/values-my-v35/strings.xml
new file mode 100644
index 000000000..4141dd6ac
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-my-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"သီးသန့်ချတ်ခန်း"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"သီးသန့်ချတ်ခန်း စသည်တို့ကို စနစ်ထည့်သွင်းသည်"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"သီးသန့်ချတ်ခန်း"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-nb-v34/strings.xml b/SafetyCenter/Resources/res/values-nb-v34/strings.xml
index f247aae19..6ccbb06bd 100644
--- a/SafetyCenter/Resources/res/values-nb-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-nb-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Helse, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Oppdateringer av datadeling for posisjon"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, datadeling, oppdateringer av datadeling, oppdateringer av datadeling for posisjon, deling"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Annonsepersonvern"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Tilpass informasjonen apper bruker for å vise deg annonser"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annonser, annonsepersonvern, Privacy Sandbox, annonseemner, annonser foreslått av apper, annonsemåling"</string>
<string name="advanced_title" msgid="6259362998269627310">"Andre innstillinger"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mer sikkerhet og personvern"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofyll, varsler med mer"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informasjon om jobbreglene dine"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-nb-v35/strings.xml b/SafetyCenter/Resources/res/values-nb-v35/strings.xml
new file mode 100644
index 000000000..5575b4d1f
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-nb-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Private Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Konfigurer Private Space med mer"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Private Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ne-v34/strings.xml b/SafetyCenter/Resources/res/values-ne-v34/strings.xml
index 4d79f599c..4a90e99b6 100644
--- a/SafetyCenter/Resources/res/values-ne-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ne-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"लोकेसन डेटा सेयर गर्नेसम्बन्धी अभ्यासका बारेमा अद्यावधिक जानकारी"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"जानकारी, जानकारी सेयर गर्नेसम्बन्धी अभ्यास, जानकारी सेयर गर्नेसम्बन्धी अभ्यासका बारेमा अद्यावधिक जानकारी, लोकेसन डेटा सेयर गर्नेसम्बन्धी अभ्यासका बारेमा अद्यावधिक जानकारी, सेयरिङ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"विज्ञापनको गोपनीयता"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"तपाईंलाई विज्ञापनहरू देखाउन एपहरूले प्रयोग गर्ने जानकारी कस्टमाइज गर्नुहोस्"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"विज्ञापन, विज्ञापनको गोपनीयता, प्राइभेसी स्यान्डबक्स, विज्ञापनको विषय, एपले सिफारिस गरेका विज्ञापनहरू, विज्ञापनको पर्फर्मेन्स मापन गर्ने सुविधा"</string>
<string name="advanced_title" msgid="6259362998269627310">"अन्य सेटिङ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"थप सुरक्षा तथा गोपनीयता"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"अटोफिल, सूचना र अन्य कुराहरू"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"तपाईंको कामसम्बन्धी नीतिको जानकारी"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ne-v35/strings.xml b/SafetyCenter/Resources/res/values-ne-v35/strings.xml
new file mode 100644
index 000000000..1d96a0c82
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ne-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"निजी स्पेस"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"निजी स्पेस सेटअप गर्नुहोस् र अन्य कार्यहरू गर्नुहोस्"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"निजी स्पेस"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ne/strings.xml b/SafetyCenter/Resources/res/values-ne/strings.xml
index 5ceab041e..4ef5c9609 100644
--- a/SafetyCenter/Resources/res/values-ne/strings.xml
+++ b/SafetyCenter/Resources/res/values-ne/strings.xml
@@ -30,7 +30,7 @@
<string name="permission_usage_title" msgid="3633779688945350407">"गोपनीयतासम्बन्धी ड्यासबोर्ड"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"हालसालै कुन कुन एपले अनुमतिहरू प्रयोग गरेका छन् भन्ने कुरा हेर्नुहोस्"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"गोपनीयता, गोपनीयतासम्बन्धी ड्यासबोर्ड"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"पर्मिसन म्यानेजर"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"अनुमति व्यवस्थापन"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"कुन कुन एपले तपाईंको डेटा प्रयोग गर्न पाउँछन् भन्ने कुरा तय गर्नुहोस्"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"अनुमतिहरू, अनुमतिसम्बन्धी प्रबन्धक"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"गोपनीयतासम्बन्धी सेटिङ"</string>
diff --git a/SafetyCenter/Resources/res/values-nl-v34/strings.xml b/SafetyCenter/Resources/res/values-nl-v34/strings.xml
index 5e4e4c729..e5a446c52 100644
--- a/SafetyCenter/Resources/res/values-nl-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-nl-v34/strings.xml
@@ -17,18 +17,16 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="lock_screen_sources_title" msgid="5493678510117489865">"Apparaatontgrendeling"</string>
+ <string name="lock_screen_sources_title" msgid="5493678510117489865">"Apparaat­ontgrendeling"</string>
<string name="biometrics_title_for_work" msgid="1842284049407771568">"Biometrische systemen voor het werk"</string>
<string name="privacy_sources_summary" msgid="4083646673569677049">"Rechten, dashboard, bedieningselementen"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"Gezondheid, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Updates voor het delen van locatiegegevens"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Gegevens, Gegevens delen, Updates voor het delen van gegevens, Updates voor het delen van locatiegegevens, delen"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Advertentieprivacy"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Pas de informatie aan die apps gebruiken om advertenties te tonen"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"advertenties, advertentieprivacy, privacy sandbox, advertentieonderwerpen, door apps voorgestelde advertenties, advertentiemeting"</string>
<string name="advanced_title" msgid="6259362998269627310">"Overige instellingen"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Meer beveiliging en privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatisch invullen, meldingen en meer"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informatie over je werkbeleid"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-nl-v35/strings.xml b/SafetyCenter/Resources/res/values-nl-v35/strings.xml
new file mode 100644
index 000000000..dc927ade3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-nl-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privéruimte"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Privéruimte instellen en meer"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privéruimte"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-nl/strings.xml b/SafetyCenter/Resources/res/values-nl/strings.xml
index 068dc5be4..5232c280b 100644
--- a/SafetyCenter/Resources/res/values-nl/strings.xml
+++ b/SafetyCenter/Resources/res/values-nl/strings.xml
@@ -30,7 +30,7 @@
<string name="permission_usage_title" msgid="3633779688945350407">"Privacydashboard"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"Toon welke apps onlangs rechten hebben gebruikt"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Privacy, Privacydashboard"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"Rechtenbeheer"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"Rechten­beheer"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Beheer de toegang van apps tot je gegevens"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Rechten, Rechtenbeheer"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Privacyopties"</string>
diff --git a/SafetyCenter/Resources/res/values-or-v34/strings.xml b/SafetyCenter/Resources/res/values-or-v34/strings.xml
index 38069cf80..df4d07e17 100644
--- a/SafetyCenter/Resources/res/values-or-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-or-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ସ୍ୱାସ୍ଥ୍ୟ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ଲୋକେସନ ପାଇଁ ଡାଟା ସେୟାରିଂ ଅପଡେଟଗୁଡ଼ିକ"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ଡାଟା, ଡାଟା ସେୟାରିଂ, ଡାଟା ସେୟାରିଂ ଅପଡେଟ, ଲୋକେସନ ପାଇଁ ଡାଟା ସେୟାରିଂ ଅପଡେଟ, ସେୟାରିଂ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ବିଜ୍ଞାପନ ଗୋପନୀୟତା"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ଆପଣଙ୍କୁ ବିଜ୍ଞାପନଗୁଡ଼ିକ ଦେଖାଇବା ପାଇଁ ଆପ୍ସ ବ୍ୟବହାର କରୁଥିବା ସୂଚନାକୁ କଷ୍ଟମାଇଜ କରନ୍ତୁ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ବିଜ୍ଞାପନ, ବିଜ୍ଞାପନ ଗୋପନୀୟତା, ପ୍ରାଇଭେସି ସେଣ୍ଡବକ୍ସ, ବିଜ୍ଞାପନ ବିଷୟ, ଆପ ଦ୍ୱାରା-ପରାମର୍ଶ ଦିଆଯାଇଥିବା ବିଜ୍ଞାପନଗୁଡ଼ିକ, ବିଜ୍ଞାପନର ପରିମାପ"</string>
<string name="advanced_title" msgid="6259362998269627310">"ଅନ୍ୟ ସେଟିଂସ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ଅଧିକ ସୁରକ୍ଷା ଏବଂ ଗୋପନୀୟତା"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ଅଟୋଫିଲ, ବିଜ୍ଞପ୍ତି ଏବଂ ଆହୁରି ଅନେକ କିଛି"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ଆପଣଙ୍କ ୱାର୍କ ନୀତି ସୂଚନା"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-or-v35/strings.xml b/SafetyCenter/Resources/res/values-or-v35/strings.xml
new file mode 100644
index 000000000..85c4fa73c
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-or-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ପ୍ରାଇଭେଟ ସ୍ପେସ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ପ୍ରାଇଭେଟ ସ୍ପେସ ଏବଂ ଆହୁରି ଅନେକ କିଛି ସେଟଅପ କରନ୍ତୁ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ପ୍ରାଇଭେଟ ସ୍ପେସ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-or/strings.xml b/SafetyCenter/Resources/res/values-or/strings.xml
index 2d3ffb67d..d4d8d1a4a 100644
--- a/SafetyCenter/Resources/res/values-or/strings.xml
+++ b/SafetyCenter/Resources/res/values-or/strings.xml
@@ -27,10 +27,10 @@
<string name="biometrics_search_terms" msgid="6040319118762671981">"ଫିଙ୍ଗରପ୍ରିଣ୍ଟ, ଆଙ୍ଗୁଠି, ଫିଙ୍ଗରପ୍ରିଣ୍ଟ ଯୋଗ କରନ୍ତୁ, ଫେସ ଅନଲକ, ଫେସ"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"ଗୋପନୀୟତା"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"ଡ୍ୟାସବୋର୍ଡ, ଅନୁମତି, ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
- <string name="permission_usage_title" msgid="3633779688945350407">"ଗୋପନୀୟତା ଡ୍ୟାସବୋର୍ଡ"</string>
+ <string name="permission_usage_title" msgid="3633779688945350407">"ଗୋପନୀୟତା ଡେସବୋର୍ଡ"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"କେଉଁ ଆପ୍ସ ଏବେ ଅନୁମତିଗୁଡ଼ିକ ବ୍ୟବହାର କରିଛି ତାହା ଦେଖାନ୍ତୁ"</string>
- <string name="permission_usage_search_terms" msgid="3852343592870257104">"ଗୋପନୀୟତା, ଗୋପନୀୟତା ଡ୍ୟାସବୋର୍ଡ"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"ଅନୁମତି ପରିଚାଳକ"</string>
+ <string name="permission_usage_search_terms" msgid="3852343592870257104">"ଗୋପନୀୟତା, ଗୋପନୀୟତା ଡେସବୋର୍ଡ"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"ପର୍ମିସନ ମେନେଜର"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"ଆପଣଙ୍କ ଡାଟାକୁ ଆପର ଆକ୍ସେସ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"ଅନୁମତି, ଅନୁମତି ପରିଚାଳକ"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"ଗୋପନୀୟତା ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
diff --git a/SafetyCenter/Resources/res/values-pa-v34/strings.xml b/SafetyCenter/Resources/res/values-pa-v34/strings.xml
index 5aa67f5c8..b30bcce37 100644
--- a/SafetyCenter/Resources/res/values-pa-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-pa-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ਸਿਹਤ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ਟਿਕਾਣੇ ਲਈ ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਅੱਪਡੇਟ"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ਡਾਟਾ, ਡਾਟਾ ਸਾਂਝਾਕਰਨ, ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਅੱਪਡੇਟ, ਟਿਕਾਣੇ ਲਈ ਡਾਟਾ ਸਾਂਝਾਕਰਨ ਅੱਪਡੇਟ, ਸਾਂਝਾਕਰਨ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ਵਿਗਿਆਪਨ ਪਰਦੇਦਾਰੀ"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ਇਹ ਵਿਉਂਤਬੱਧ ਕਰੋ ਕਿ ਐਪਾਂ ਤੁਹਾਨੂੰ ਵਿਗਿਆਪਨ ਦਿਖਾਉਣ ਲਈ ਕਿਹੜੀ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀਆਂ ਹਨ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"ਵਿਗਿਆਪਨ, ਵਿਗਿਆਪਨ ਪਰਦੇਦਾਰੀ, ਪ੍ਰਾਈਵੇਸੀ ਸੈਂਡਬਾਕਸ, ਵਿਗਿਆਪਨ ਦੇ ਵਿਸ਼ੇ, ਐਪ ਵੱਲੋਂ ਸੁਝਾਏ ਵਿਗਿਆਪਨ, ਵਿਗਿਆਪਨ ਮਾਪ"</string>
<string name="advanced_title" msgid="6259362998269627310">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ਹੋਰ ਸੁਰੱਖਿਆ ਅਤੇ ਪਰਦੇਦਾਰੀ"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ਆਟੋਫਿਲ, ਸੂਚਨਾਵਾਂ ਅਤੇ ਹੋਰ"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ਤੁਹਾਡੀ ਕਾਰਜ ਨੀਤੀ ਸੰਬੰਧੀ ਜਾਣਕਾਰੀ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-pa-v35/strings.xml b/SafetyCenter/Resources/res/values-pa-v35/strings.xml
new file mode 100644
index 000000000..f1e2dd714
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pa-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ਨਿੱਜੀ ਸਪੇਸ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ਨਿੱਜੀ ਸਪੇਸ ਦਾ ਸੈੱਟਅੱਪ ਅਤੇ ਹੋਰ ਕੰਮ ਕਰੋ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ਨਿੱਜੀ ਸਪੇਸ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pl-v34/strings.xml b/SafetyCenter/Resources/res/values-pl-v34/strings.xml
index bf39edf14..7ee39b539 100644
--- a/SafetyCenter/Resources/res/values-pl-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-pl-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Zmiany w udostępnianiu danych o lokalizacji"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"dane, udostępnianie danych, zmiany w udostępnianiu danych, zmiany w udostępnianiu danych o lokalizacji, udostępnianie"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Prywatność w reklamach"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Dostosuj informacje używane przez aplikacje przy wyświetlaniu reklam"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamy, prywatność w reklamach, Piaskownica prywatności, tematy reklam, reklamy sugerowane przez aplikację, pomiar skuteczności reklam"</string>
<string name="advanced_title" msgid="6259362998269627310">"Inne ustawienia"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Więcej ustawień bezpieczeństwa i prywatności"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autouzupełnianie, powiadomienia i inne ustawienia"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informacje o zasadach obowiązujących w firmie"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-pl-v35/strings.xml b/SafetyCenter/Resources/res/values-pl-v35/strings.xml
new file mode 100644
index 000000000..56c410a05
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pl-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Obszar prywatny"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Skonfiguruj obszar prywatny i inne ustawienia"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Obszar prywatny"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rBR-v34/strings.xml b/SafetyCenter/Resources/res/values-pt-rBR-v34/strings.xml
index 8a11ca969..a69cf32ca 100644
--- a/SafetyCenter/Resources/res/values-pt-rBR-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-rBR-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Saúde, Conexão Saúde"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Atualizações no compartilhamento de dados de local"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dados, Compartilhamento de dados, Atualizações de compartilhamento de dados, Atualizações de compartilhamento de dados para localização, compartilhamento"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidade de anúncios"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalize as informações que os apps usam para mostrar anúncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anúncios, privacidade de anúncios, Sandbox de privacidade, temas de anúncios, anúncios sugeridos por apps, medição de anúncio"</string>
<string name="advanced_title" msgid="6259362998269627310">"Outras configurações"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mais segurança e privacidade"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Preenchimento automático, notificações e mais"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informações sobre sua política de trabalho"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml
new file mode 100644
index 000000000..ef0c3c738
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espaço particular"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configurar Espaço particular e mais"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espaço particular"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rPT-v34/strings.xml b/SafetyCenter/Resources/res/values-pt-rPT-v34/strings.xml
index e768cce11..643fa469d 100644
--- a/SafetyCenter/Resources/res/values-pt-rPT-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-rPT-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Saúde, Saúde Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Atualizações da partilha de dados para a localização"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dados, partilha de dados, atualizações de partilha de dados, atualizações da partilha de dados para a localização, partilha"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidade dos anúncios"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalize as informações que as apps usam para lhe mostrar anúncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anúncios, privacidade de anúncios, Privacy Sandbox, tópicos de anúncios, anúncios sugeridos por apps, medição de anúncios"</string>
<string name="advanced_title" msgid="6259362998269627310">"Outras definições"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Maior segurança e privacidade"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Preenchimento automático, notificações e muito mais"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"As suas informações da Política de Trabalho"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml
new file mode 100644
index 000000000..6e397ccf0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espaço privado"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configure o espaço privado e muito mais"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espaço privado"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-rPT/strings.xml b/SafetyCenter/Resources/res/values-pt-rPT/strings.xml
index 80fda0dde..5773d657b 100644
--- a/SafetyCenter/Resources/res/values-pt-rPT/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-rPT/strings.xml
@@ -28,7 +28,7 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"Privacidade"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Painel de controlo, autorizações e controlos"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Painel de privacidade"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"Mostrar apps que usaram autorizações recentemente"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"Mostre apps que usaram autorizações recentemente"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Privacidade, painel de privacidade"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Gestor de autorizações"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Controle o acesso de apps aos seus dados"</string>
diff --git a/SafetyCenter/Resources/res/values-pt-v34/strings.xml b/SafetyCenter/Resources/res/values-pt-v34/strings.xml
index 8a11ca969..a69cf32ca 100644
--- a/SafetyCenter/Resources/res/values-pt-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Saúde, Conexão Saúde"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Atualizações no compartilhamento de dados de local"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dados, Compartilhamento de dados, Atualizações de compartilhamento de dados, Atualizações de compartilhamento de dados para localização, compartilhamento"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacidade de anúncios"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalize as informações que os apps usam para mostrar anúncios"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anúncios, privacidade de anúncios, Sandbox de privacidade, temas de anúncios, anúncios sugeridos por apps, medição de anúncio"</string>
<string name="advanced_title" msgid="6259362998269627310">"Outras configurações"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mais segurança e privacidade"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Preenchimento automático, notificações e mais"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informações sobre sua política de trabalho"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-pt-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-v35/strings.xml
new file mode 100644
index 000000000..ef0c3c738
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-pt-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Espaço particular"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configurar Espaço particular e mais"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Espaço particular"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ro-v34/strings.xml b/SafetyCenter/Resources/res/values-ro-v34/strings.xml
index 1ac0f0fce..9292c43d3 100644
--- a/SafetyCenter/Resources/res/values-ro-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ro-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Actualizări privind permiterea accesului la date pentru locație"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"date, permiterea accesului la date, actualizări privind permiterea accesului la date, actualizări privind permiterea accesului la date pentru locație, permiterea accesului"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Confidențialitatea anunțurilor"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Personalizează informațiile pe care le folosesc aplicațiile pentru a-ți afișa anunțuri"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"anunțuri, confidențialitatea anunțurilor, privacy sandbox, subiectele anunțurilor, anunțuri sugerate de aplicații, cuantificarea anunțurilor"</string>
<string name="advanced_title" msgid="6259362998269627310">"Alte setări"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mai multe setări pentru securitate și confidențialitate"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Completare automată, notificări și altele"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informații despre politica privind activitatea"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ro-v35/strings.xml b/SafetyCenter/Resources/res/values-ro-v35/strings.xml
new file mode 100644
index 000000000..5884075bf
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ro-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Spațiu privat"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Configurează Spațiul privat și altele"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Spațiu privat"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ru-v34/strings.xml b/SafetyCenter/Resources/res/values-ru-v34/strings.xml
index c2134acb9..b8a78d5ed 100644
--- a/SafetyCenter/Resources/res/values-ru-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ru-v34/strings.xml
@@ -22,13 +22,11 @@
<string name="privacy_sources_summary" msgid="4083646673569677049">"Разрешения, панель управления, параметры"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Здоровье и спорт"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"Здоровье, Здоровье и спорт"</string>
- <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Обновление доступа к данным о местоположении"</string>
+ <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Обновления в передаче данных о местоположении"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Данные, Передача данных, Обновления передачи данных, Обновление доступа к данным, Обновление доступа к данным о местоположении"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Конфиденциальность в рекламе"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Укажите, какую информацию приложения могут использовать для показа рекламы"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"объявления, конфиденциальность в рекламе, privacy sandbox, темы объявлений, реклама, предлагаемая приложениями, оценка эффективности рекламы"</string>
<string name="advanced_title" msgid="6259362998269627310">"Другие настройки"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Дополнительные настройки безопасности и конфиденциальности"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автозаполнение, уведомления и другие настройки"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Сведения о правилах организации"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ru-v35/strings.xml b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
new file mode 100644
index 000000000..29a17d7a9
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Личное пространство"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Настройка личного пространства и не только"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Личное пространство"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ru/strings.xml b/SafetyCenter/Resources/res/values-ru/strings.xml
index aaa71ae29..715e7ebb4 100644
--- a/SafetyCenter/Resources/res/values-ru/strings.xml
+++ b/SafetyCenter/Resources/res/values-ru/strings.xml
@@ -31,7 +31,7 @@
<string name="permission_usage_summary" msgid="5323079206029964468">"Посмотреть, какие приложения недавно использовали разрешения"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Конфиденциальность, панель управления разрешениями"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Управление разрешениями"</string>
- <string name="permission_manager_summary" msgid="8099852107340970790">"Настройки доступа приложений к вашим данным"</string>
+ <string name="permission_manager_summary" msgid="8099852107340970790">"Настроить доступ приложений к вашим данным"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Разрешения, управление разрешениями"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Настройки конфиденциальности"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Настройки доступа к микрофону, камере и прочему"</string>
diff --git a/SafetyCenter/Resources/res/values-si-v34/strings.xml b/SafetyCenter/Resources/res/values-si-v34/strings.xml
index 0a54811f0..b2b291351 100644
--- a/SafetyCenter/Resources/res/values-si-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-si-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"සෞඛ්‍යය, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"ස්ථානය සඳහා දත්ත බෙදා ගැනීමේ යාවත්කාලීන"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"දත්ත, දත්ත බෙදා ගැනීම, දත්ත බෙදා ගැනීමේ යාවත්කාලීන, ස්ථානය සඳහා දත්ත බෙදා ගැනීමේ යාවත්කාලීන, බෙදා ගැනීම"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"දැන්වීම් පෞද්ගලිකත්වය"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ඔබට දැන්වීම් පෙන්වීමට යෙදුම් භාවිතා කරන තතු අභිරුචිකරණය කරන්න"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"දැන්වීම්, දැන්වීම් පෞද්ගලිකත්වය, පෞද්ගලිකත්ව සෑන්ඩ්බොක්ස්, දැන්වීම් මාතෘකා, යෙදුම්-යෝජිත දැන්වීම්, දැන්වීම් මැනීම"</string>
<string name="advanced_title" msgid="6259362998269627310">"වෙනත් සැකසීම්"</string>
<string name="more_settings_title" msgid="9033454654010697185">"තව ආරක්ෂාව සහ පෞද්ගලිකත්වය"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ස්වයං පිරවීම, දැනුම්දීම්, සහ තවත් දේ"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ඔබේ කාර්යාල ප්‍රතිපත්ති තතු"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-si-v35/strings.xml b/SafetyCenter/Resources/res/values-si-v35/strings.xml
new file mode 100644
index 000000000..c3605e2a1
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-si-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"පෞද්ගලික ඉඩ"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"පෞද්ගලික ඉඩ, සහ තවත් දේ පිහිටුවන්න"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"පෞද්ගලික ඉඩ"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sk-v34/strings.xml b/SafetyCenter/Resources/res/values-sk-v34/strings.xml
index 4b788d9fd..c3cdab5d2 100644
--- a/SafetyCenter/Resources/res/values-sk-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sk-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Zdravie, Dáta o zdraví"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Aktualizácie zdieľania údajov o polohe"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Údaje, zdieľanie údajov, aktualizácie zdieľania údajov, aktualizácie zdieľania údajov o polohe, zdieľanie"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ochrana súkromia pri reklamách"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Prispôsobovať informácie, podľa ktorých aplikácie zobrazujú reklamy"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamy, ochrana súkromia pri reklamách, technológie privacy sandbox, témy reklám, reklamy navrhované aplikáciami, meranie reklám"</string>
<string name="advanced_title" msgid="6259362998269627310">"Ďalšie nastavenia"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Ďalšie zabezpečenie a ochrana súkromia"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Automatické dopĺňanie, upozornenia a ďalšie možnosti"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informácie o pracovných pravidlách"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sk-v35/strings.xml b/SafetyCenter/Resources/res/values-sk-v35/strings.xml
new file mode 100644
index 000000000..bed329c6b
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sk-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Súkromný priestor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Nastavte súkromný priestor a ďalšie možnosti"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Súkromný priestor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sl-v34/strings.xml b/SafetyCenter/Resources/res/values-sl-v34/strings.xml
index af8c92884..9898c2f0a 100644
--- a/SafetyCenter/Resources/res/values-sl-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sl-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"zdravje, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Posodobitve deljenja podatkov o lokaciji"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"podatki, deljenje podatkov, posodobitve deljenja podatkov, posodobitve deljenja podatkov o lokaciji, deljenje"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Zasebnost pri oglaševanju"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Prilagodite, katere podatke uporabljajo aplikacije za prikazovanje oglasov."</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"oglasi, zasebnost pri oglaševanju, zasebni peskovnik, teme oglasov, oglasi na predlog aplikacij, merjenje oglasov"</string>
<string name="advanced_title" msgid="6259362998269627310">"Druge nastavitve"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Več varnosti in zasebnosti"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Samodejno izpolnjevanje, obvestila in drugo"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Podatki o službenem pravilniku"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sl-v35/strings.xml b/SafetyCenter/Resources/res/values-sl-v35/strings.xml
new file mode 100644
index 000000000..aa7a10258
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sl-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Zasebni prostor"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Nastavitev zasebnega prostora in drugo"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Zasebni prostor"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sq-v34/strings.xml b/SafetyCenter/Resources/res/values-sq-v34/strings.xml
index 9306ad77d..64d7f4a4e 100644
--- a/SafetyCenter/Resources/res/values-sq-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sq-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Shëndeti, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Përditësime për ndarjen e të dhënave për vendndodhjen"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Të dhënat, ndarja e të dhënave, përditësimet për ndarjen e të dhënave, përditësimet për ndarjen e të dhënave për vendndodhjen, ndarja"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privatësia e reklamave"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Informacionet e personalizuara që aplikacionet përdorin për të të shfaqur reklama"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamat, privatësia e reklamave, privacy sandbox, temat e reklamave, reklamat e sugjeruara nga aplikacionet, matja e reklamave"</string>
<string name="advanced_title" msgid="6259362998269627310">"Cilësime të tjera"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Më shumë siguri dhe privatësi"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Plotësimi automatik, njoftimet dhe më shumë"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Informacioni i politikës së punës"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sq-v35/strings.xml b/SafetyCenter/Resources/res/values-sq-v35/strings.xml
new file mode 100644
index 000000000..63c642f89
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sq-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Hapësira private"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Konfiguro \"Hapësirën private\" dhe të tjera"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Hapësira private"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sr-v34/strings.xml b/SafetyCenter/Resources/res/values-sr-v34/strings.xml
index 474c6a35d..9c69c8fad 100644
--- a/SafetyCenter/Resources/res/values-sr-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sr-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"здравље, повезивање здравља"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Ажурирања дељења података за локацију"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"подаци, дељење података, ажурирања дељења података, ажурирања дељења података за локацију, дељење"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Приватност са огласима"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Прилагодите информације које апликације користе да би вам приказивале огласе"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"огласи, приватност са огласима, заштићено окружење приватности, теме огласа, огласи које предлажу апликације, мерење огласа"</string>
<string name="advanced_title" msgid="6259362998269627310">"Остала подешавања"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Још безбедности и приватности"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Аутоматско попуњавање, обавештења и друго"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Информације о смерницама за посао"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sr-v35/strings.xml b/SafetyCenter/Resources/res/values-sr-v35/strings.xml
new file mode 100644
index 000000000..b2349b10a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sr-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Приватни простор"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Подесите приватни простор и друго"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Приватни простор"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sr/strings.xml b/SafetyCenter/Resources/res/values-sr/strings.xml
index 4642ec771..2cd42d24c 100644
--- a/SafetyCenter/Resources/res/values-sr/strings.xml
+++ b/SafetyCenter/Resources/res/values-sr/strings.xml
@@ -20,7 +20,7 @@
<string name="safetyCenterResourcesAppLabel" msgid="4043334186295695930">"Ресурси Центра за безбедност"</string>
<string name="lock_screen_sources_title" msgid="3317906280484627707">"Закључавање уређаја"</string>
<string name="lock_screen_sources_summary" msgid="7220439741282516496"></string>
- <string name="lock_screen_title" msgid="4069104894527169877">"Закључавање екрана"</string>
+ <string name="lock_screen_title" msgid="4069104894527169877">"Откључавање екрана"</string>
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Још нема информација"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"закључавање уређаја, закључавање екрана, закључани екран, лозинка, PIN, шаблон"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Биометрија"</string>
diff --git a/SafetyCenter/Resources/res/values-sv-v34/strings.xml b/SafetyCenter/Resources/res/values-sv-v34/strings.xml
index 3957a5e76..ef7de6322 100644
--- a/SafetyCenter/Resources/res/values-sv-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sv-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Hälsa, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Uppdateringar om datadelning för plats"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Datadelning, Uppdateringar om datadelning, Uppdateringar om datadelning för plats, delning"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Annonsintegritet"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Anpassa information som appar använder för att visa annonser"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"annonser, annonsintegritet, privacy sandbox, annonsämnen, föreslagna annonser i appar, annonsmätning"</string>
<string name="advanced_title" msgid="6259362998269627310">"Andra inställningar"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Mer säkerhet och integritet"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofyll, aviseringar med mera"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Information om jobbprincip"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sv-v35/strings.xml b/SafetyCenter/Resources/res/values-sv-v35/strings.xml
new file mode 100644
index 000000000..85e0e6a7d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sv-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Privat rum"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Ställ in privat rum med mera"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Privat rum"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-sw-v34/strings.xml b/SafetyCenter/Resources/res/values-sw-v34/strings.xml
index a9cb44a50..d065e2e03 100644
--- a/SafetyCenter/Resources/res/values-sw-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-sw-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Afya, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Masasisho ya kushiriki data ya mahali"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, kushiriki Data, masasisho ya kushiriki Data, Masasisho ya kushiriki data ya mahali, kushiriki"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Faragha ya matangazo"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Weka mapendeleo ya maelezo yanayotumiwa na programu kukuonyesha matangazo"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"matangazo, faragha ya matangazo, mazingira ya faragha, mada za tangazo, matangazo yanayopendekezwa na programu, upimaji wa tangazo"</string>
<string name="advanced_title" msgid="6259362998269627310">"Mipangilio mingine"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Usalama na faragha zaidi"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Kujaza kiotomatiki, arifa na zaidi"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Maelezo ya sera ya kazini"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-sw-v35/strings.xml b/SafetyCenter/Resources/res/values-sw-v35/strings.xml
new file mode 100644
index 000000000..9ef8839b5
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-sw-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Nafasi ya Faragha"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Weka mipangilio ya Nafasi ya Faragha na zaidi"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Nafasi ya Faragha"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-ta-v34/strings.xml b/SafetyCenter/Resources/res/values-ta-v34/strings.xml
index e59f639c9..b9f2a0b4e 100644
--- a/SafetyCenter/Resources/res/values-ta-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ta-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"இருப்பிடத்திற்கான தரவுப் பகிர்வு குறித்த அறிவிப்புகள்"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"தரவு, தரவுப் பகிர்வு, தரவுப் பகிர்வு குறித்த அறிவிப்புகள், இருப்பிடத்திற்கான தரவுப் பகிர்வு குறித்த அறிவிப்புகள், பகிர்வு"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"விளம்பரங்கள் தொடர்பான தனியுரிமை"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"உங்களுக்கு விளம்பரங்களைக் காட்டுவதற்காக ஆப்ஸ் பயன்படுத்தும் தகவல்களைப் பிரத்தியேகமாக்கலாம்"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"விளம்பரங்கள், விளம்பரங்கள் தொடர்பான தனியுரிமை, தனியுரிமை சாண்ட்பாக்ஸ், விளம்பரத் தலைப்புகள், ஆப்ஸால் பரிந்துரைக்கப்படும் விளம்பரங்கள், விளம்பர அளவீடு"</string>
<string name="advanced_title" msgid="6259362998269627310">"மற்ற அமைப்புகள்"</string>
<string name="more_settings_title" msgid="9033454654010697185">"கூடுதல் பாதுகாப்பு மற்றும் தனியுரிமை"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"தன்னிரப்பி, அறிவிப்புகள் மற்றும் பல"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"உங்கள் பணிக் கொள்கை பற்றிய தகவல்கள்"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ta-v35/strings.xml b/SafetyCenter/Resources/res/values-ta-v35/strings.xml
new file mode 100644
index 000000000..73591d1b0
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ta-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"தனிப்பட்ட சேமிப்பிடம்"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"தனிப்பட்ட சேமிப்பிடத்தை அமைக்கலாம் மற்றும் பலவற்றைச் செய்யலாம்"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"தனிப்பட்ட சேமிப்பிடம்"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-te-v34/strings.xml b/SafetyCenter/Resources/res/values-te-v34/strings.xml
index 6c9318f24..9ca7bea5f 100644
--- a/SafetyCenter/Resources/res/values-te-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-te-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"ఆరోగ్యం, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"లొకేషన్‌కు సంబంధించిన డేటా షేరింగ్ అప్‌డేట్‌లు"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"డేటా, డేటా షేరింగ్, డేటా షేరింగ్ అప్‌డేట్‌లు, లొకేషన్‌కు సంబంధించిన డేటా షేరింగ్ అప్‌డేట్‌లు, షేరింగ్"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"యాడ్‌ల విషయంలో గోప్యత"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"మీకు యాడ్‌లను చూపడానికి ఉపయోగించే సమాచార యాప్‌లను అనుకూలంగా మార్చండి"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"యాడ్‌లు, యాడ్‌ల విషయంలో గోప్యత, గోప్యతా పరిరక్షణ టెక్నాలజీల సెట్, యాడ్ టాపిక్‌లు, యాప్-సూచించిన యాడ్‌లు, యాడ్ మెజర్‌మెంట్"</string>
<string name="advanced_title" msgid="6259362998269627310">"ఇతర సెట్టింగ్‌లు"</string>
<string name="more_settings_title" msgid="9033454654010697185">"మరింత సెక్యూరిటీ &amp; గోప్యత"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"ఆటోఫిల్, నోటిఫికేషన్‌లు, అలాగే మరెన్నో"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"మీ వర్క్ పాలసీ సమాచారం"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-te-v35/strings.xml b/SafetyCenter/Resources/res/values-te-v35/strings.xml
new file mode 100644
index 000000000..ffccea816
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-te-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"ప్రైవేట్ స్పేస్"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ప్రైవేట్ స్పేస్‌ను సెటప్ చేయండి, మరెన్నింటినో చేయండి"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"ప్రైవేట్ స్పేస్"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-te/strings.xml b/SafetyCenter/Resources/res/values-te/strings.xml
index 6763b1672..11c181a9c 100644
--- a/SafetyCenter/Resources/res/values-te/strings.xml
+++ b/SafetyCenter/Resources/res/values-te/strings.xml
@@ -28,10 +28,10 @@
<string name="privacy_sources_title" msgid="4061110826457365957">"గోప్యత"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"డ్యాష్‌బోర్డ్, అనుమతులు, కంట్రోల్స్"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"గోప్యతా డ్యాష్‌బోర్డ్"</string>
- <string name="permission_usage_summary" msgid="5323079206029964468">"ఇటీవల ఏ యాప్‌లు అనుమతులను ఉపయోగించాయో చూపించండి"</string>
+ <string name="permission_usage_summary" msgid="5323079206029964468">"ఇటీవల ఏ యాప్‌లు అనుమతులను ఉపయోగించాయో చూపిస్తుంది"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"గోప్యత, గోప్యతా డ్యాష్‌బోర్డ్"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"అనుమతి మేనేజర్"</string>
- <string name="permission_manager_summary" msgid="8099852107340970790">"మీ డేటాకు యాప్ యాక్సెస్‌ను కంట్రోల్ చేయండి"</string>
+ <string name="permission_manager_summary" msgid="8099852107340970790">"మీ డేటాకు యాప్ యాక్సెస్‌ను కంట్రోల్ చేస్తుంది"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"అనుమతులు, అనుమతుల మేనేజర్"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"గోప్యతా కంట్రోల్స్"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"మైక్రోఫోన్, కెమెరా, మరిన్నింటికి డివైజ్ యాక్సెస్‌ను కంట్రోల్ చేయండి"</string>
diff --git a/SafetyCenter/Resources/res/values-th-v34/strings.xml b/SafetyCenter/Resources/res/values-th-v34/strings.xml
index b323131b5..e334d9b5e 100644
--- a/SafetyCenter/Resources/res/values-th-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-th-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"สุขภาพ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"การอัปเดตการแชร์ข้อมูลตำแหน่ง"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ข้อมูล, การแชร์ข้อมูล, การอัปเดตการแชร์ข้อมูล, การอัปเดตการแชร์ข้อมูลตำแหน่ง, การแชร์"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"ความเป็นส่วนตัวเกี่ยวกับโฆษณา"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"ปรับแต่งข้อมูลที่แอปใช้เพื่อแสดงโฆษณาต่อคุณ"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"โฆษณา, ความเป็นส่วนตัวเกี่ยวกับโฆษณา, Privacy Sandbox, หัวข้อโฆษณา, โฆษณาที่แอปแนะนำ, การวัดผลโฆษณา"</string>
<string name="advanced_title" msgid="6259362998269627310">"การตั้งค่าอื่นๆ"</string>
<string name="more_settings_title" msgid="9033454654010697185">"ความปลอดภัยและความเป็นส่วนตัวเพิ่มเติม"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"การป้อนข้อความอัตโนมัติ การแจ้งเตือน และอื่นๆ"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"ข้อมูลนโยบายการทำงาน"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-th-v35/strings.xml b/SafetyCenter/Resources/res/values-th-v35/strings.xml
new file mode 100644
index 000000000..f16443413
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-th-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"พื้นที่ส่วนตัว"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"ตั้งค่าพื้นที่ส่วนตัวและอื่นๆ"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"พื้นที่ส่วนตัว"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-tl-v34/strings.xml b/SafetyCenter/Resources/res/values-tl-v34/strings.xml
index ef498d390..dd3754f15 100644
--- a/SafetyCenter/Resources/res/values-tl-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-tl-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Kalusugan, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Mga update sa pagbabahagi ng data para sa lokasyon"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Data, Pagbabahagi ng data, Mga update sa pagbabahagi ng data, Mga update sa pagbabahagi ng data para sa lokasyon, pagbabahagi"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Privacy sa ad"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"I-customize ang impormasyong ginagamit ng mga app para makapagpakita sa iyo ng mga ad"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"mga ad, privacy sa ad, privacy sandbox, mga paksa ng ad, mga ad na iminumungkahi ng app, pagsusukat ng ad"</string>
<string name="advanced_title" msgid="6259362998269627310">"Iba pang setting"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Higit na seguridad at privacy"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Autofill, mga notification, at higit pa"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Impormasyon tungkol sa iyong patakaran sa trabaho"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-tl-v35/strings.xml b/SafetyCenter/Resources/res/values-tl-v35/strings.xml
new file mode 100644
index 000000000..f28f2ba45
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-tl-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Pribadong Space"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"I-set up ang Pribadong Space, at higit pa"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Pribadong Space"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-tr-v34/strings.xml b/SafetyCenter/Resources/res/values-tr-v34/strings.xml
index 8cf812a85..9d330c3ce 100644
--- a/SafetyCenter/Resources/res/values-tr-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-tr-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Sağlık, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Konum için veri paylaşımı güncellemeleri"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Veri, Veri paylaşımı, Veri paylaşımı güncellemeleri, Konum için veri paylaşımı güncellemeleri, paylaşım"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Reklam gizliliği"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Uygulamaların size reklam göstermek için kullandığı bilgileri özelleştirin"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklamlar, reklam gizliliği, özel korumalı alan, reklam konuları, uygulama tarafından önerilen reklamlar, reklam ölçümü"</string>
<string name="advanced_title" msgid="6259362998269627310">"Diğer ayarlar"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Daha fazla güvenlik ve gizlilik"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Otomatik doldurma, bildirimler ve daha fazlası"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"İş politikası bilgileriniz"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-tr-v35/strings.xml b/SafetyCenter/Resources/res/values-tr-v35/strings.xml
new file mode 100644
index 000000000..26977f3d3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-tr-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Gizli Alan"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Gizli alan yapılandırma ve daha fazlası"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Gizli Alan"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uk-v34/strings.xml b/SafetyCenter/Resources/res/values-uk-v34/strings.xml
index b865ed57d..9d2ba565f 100644
--- a/SafetyCenter/Resources/res/values-uk-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-uk-v34/strings.xml
@@ -22,13 +22,11 @@
<string name="privacy_sources_summary" msgid="4083646673569677049">"Дозволи, панель керування, налаштування"</string>
<string name="health_connect_title" msgid="8318152190040327804">"Health Connect"</string>
<string name="health_connect_search_terms" msgid="4998970586245680829">"Здоров’я, Health Connect"</string>
- <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Оновлення способу передавання геоданих"</string>
+ <string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Зміни в передаванні геоданих"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Дані, передавання даних, оновлення способу передавання даних, оновлення способу передавання геоданих, передавання"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Конфіденційність у рекламі"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Налаштуйте типи інформації, на основі якої додатки показуватимуть вам рекламу"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"реклама, конфіденційність у рекламі, privacy sandbox, теми оголошень, пропонована додатками реклама, вимірювання ефективності реклами"</string>
<string name="advanced_title" msgid="6259362998269627310">"Інші налаштування"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Краща безпека й конфіденційність"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Автозаповнення, сповіщення тощо"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Інформація про правила організації"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-uk-v35/strings.xml b/SafetyCenter/Resources/res/values-uk-v35/strings.xml
new file mode 100644
index 000000000..4478750ab
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-uk-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Приватний простір"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Налаштуйте приватний простір тощо"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Приватний простір"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uk/strings.xml b/SafetyCenter/Resources/res/values-uk/strings.xml
index b7f6342db..0c1e109a3 100644
--- a/SafetyCenter/Resources/res/values-uk/strings.xml
+++ b/SafetyCenter/Resources/res/values-uk/strings.xml
@@ -24,13 +24,13 @@
<string name="lock_screen_summary_disabled" msgid="354071230916616692">"Поки немає інформації"</string>
<string name="lock_screen_search_terms" msgid="2678486357779794826">"блокування пристрою, блокування екрана, блокувати екран, заблокований екран, пароль, PIN-код, ключ"</string>
<string name="biometrics_title" msgid="5859504610285212938">"Біометрія"</string>
- <string name="biometrics_search_terms" msgid="6040319118762671981">"відбиток пальця, палець, додати відбиток пальця, фейсконтроль, обличчя"</string>
+ <string name="biometrics_search_terms" msgid="6040319118762671981">"відбиток пальця, палець, додати відбиток пальця, фейс-контроль, обличчя"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Конфіденційність"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Панель керування, дозволи, параметри"</string>
<string name="permission_usage_title" msgid="3633779688945350407">"Панель керування дозволами"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"Перегляньте, які додатки нещодавно використовували дозволи"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"конфіденційність, панель керування дозволами"</string>
- <string name="permission_manager_title" msgid="5277347862821255015">"Диспетчер дозволів"</string>
+ <string name="permission_manager_title" msgid="5277347862821255015">"Менеджер дозволів"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Контролюйте доступ додатка до даних"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"дозволи, диспетчер дозволів"</string>
<string name="privacy_controls_title" msgid="5322875777945432395">"Налаштування конфіденційності"</string>
diff --git a/SafetyCenter/Resources/res/values-ur-v34/strings.xml b/SafetyCenter/Resources/res/values-ur-v34/strings.xml
index b03da6a69..eb6e1e407 100644
--- a/SafetyCenter/Resources/res/values-ur-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-ur-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"‏صحت، Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"مقام کے لیے ڈیٹا کے اشتراک کی اپ ڈیٹس"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"ڈیٹا، ڈیٹا کا اشتراک، ڈیٹا کے اشتراک کی اپ ڈیٹس، ڈیٹا کے اشتراک کی اپ ڈیٹس برائے مقام، اشتراک کرنا"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"اشتہار کی رازداری"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"اس معلومات کو حسب ضرورت بنائیں جس کو ایپس آپ کو اشتہارات دکھانے کیلئے استعمال کرتی ہیں"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"اشتہارات، اشتہار کی رازداری، رازداری سینڈ باکس، اشتہار کے عنوانات، ایپس کے تجویز کردہ اشتہارات، اشتہار کی پیمائش"</string>
<string name="advanced_title" msgid="6259362998269627310">"دیگر ترتیبات"</string>
<string name="more_settings_title" msgid="9033454654010697185">"مزید سیکیورٹی اور رازداری"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"آٹوفل، اطلاعات اور مزید"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"آپ کے کام سے متعلق پالیسی کی معلومات"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ur-v35/strings.xml b/SafetyCenter/Resources/res/values-ur-v35/strings.xml
new file mode 100644
index 000000000..c506baa97
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-ur-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"نجی اسپیس"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"نجی اسپیس اور بھی بہت کچھ سیٹ اپ کریں"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"نجی اسپیس"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uz-v34/strings.xml b/SafetyCenter/Resources/res/values-uz-v34/strings.xml
index 8c85eedea..1304a81f6 100644
--- a/SafetyCenter/Resources/res/values-uz-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-uz-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Joylashuv axboroti ulashuvida oʻzgarishlar"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Maʼlumotlar, maʼlumotlar ulashuvi, maʼlumotlar ulashuvi yangilanishi, joylashuv axboroti ulashuvida oʻzgarishlar, ulashuv"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Reklamadagi maxfiylik"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Reklamalarni chiqarishda ilovalar foydalanadigan maʼlumotlarni belgilang"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"reklama, reklamada maxfiylik, maxfiylik sinovi, reklama mavzulari, ilova taklif qiladigan reklama, reklama hisoblanishi"</string>
<string name="advanced_title" msgid="6259362998269627310">"Boshqa sozlamalar"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Qoʻshimcha xavfsizlik va maxfiylik sozlamalari"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Avtomatik kiritish, bildirishnomalar va boshqalar"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Ish siyosati haqida axborot"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-uz-v35/strings.xml b/SafetyCenter/Resources/res/values-uz-v35/strings.xml
new file mode 100644
index 000000000..d8813cc82
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-uz-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Maxfiy joy"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Maxfiy joyni sozlash"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Maxfiy joy"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-uz/strings.xml b/SafetyCenter/Resources/res/values-uz/strings.xml
index 2d99d80b2..f97bfa320 100644
--- a/SafetyCenter/Resources/res/values-uz/strings.xml
+++ b/SafetyCenter/Resources/res/values-uz/strings.xml
@@ -27,7 +27,7 @@
<string name="biometrics_search_terms" msgid="6040319118762671981">"Barmoq izi, barmoq, barmoq izi qoʻshish, yuz bilan ochish, yuz"</string>
<string name="privacy_sources_title" msgid="4061110826457365957">"Maxfiylik"</string>
<string name="privacy_sources_summary" msgid="4089719981155120864">"Boshqaruv paneli, ruxsatlar, boshqaruv"</string>
- <string name="permission_usage_title" msgid="3633779688945350407">"Maxfiylik boshqaruv paneli"</string>
+ <string name="permission_usage_title" msgid="3633779688945350407">"Maxfiylik boshqaruvi"</string>
<string name="permission_usage_summary" msgid="5323079206029964468">"Oxirgi marta qaysi ilovalar ruxsatlardan foydalanganini koʻrsatish"</string>
<string name="permission_usage_search_terms" msgid="3852343592870257104">"Maxfiylik, maxfiylik boshqaruv paneli"</string>
<string name="permission_manager_title" msgid="5277347862821255015">"Ruxsatlar boshqaruvi"</string>
diff --git a/SafetyCenter/Resources/res/values-v34/config.xml b/SafetyCenter/Resources/res/values-v34/config.xml
index db79e5924..c3e1e38a2 100644
--- a/SafetyCenter/Resources/res/values-v34/config.xml
+++ b/SafetyCenter/Resources/res/values-v34/config.xml
@@ -20,4 +20,6 @@
<string name="config_same_task_safety_source_ids" translatable="false">AndroidAccessibility,AndroidBackgroundLocation,AndroidBiometrics,AndroidHealthConnect,AndroidLockScreen,AndroidMoreSettings,AndroidNotificationListener,AndroidPermissionAutoRevoke,AndroidPermissionManager,AndroidPermissionUsage,AndroidPrivacyAppDataSharingUpdates,AndroidPrivacyControls,AndroidWorkPolicyInfo</string>
<!-- Comma separated list of safety source IDs to add an Intent Extra confirming they should be displayed as if opened by a settings UI page. -->
<string name="config_useSettingsHomepageIntentExtra" translatable="false">AndroidMoreSettings,TestSource</string>
+ <!-- Comma separated list of safety source IDs that should be refreshed on page open by default. -->
+ <string name="config_defaultRefreshOnPageOpenSources" translatable="false">AndroidBiometrics</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-v35/config.xml b/SafetyCenter/Resources/res/values-v35/config.xml
new file mode 100644
index 000000000..3d8ac11ea
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-v35/config.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Comma separated list of safety source IDs to show in the same task as the safety center -->
+ <string name="config_same_task_safety_source_ids" translatable="false">AndroidAccessibility,AndroidBackgroundLocation,AndroidBiometrics,AndroidHealthConnect,AndroidLockScreen,AndroidPrivateSpace,AndroidMoreSettings,AndroidNotificationListener,AndroidPermissionAutoRevoke,AndroidPermissionManager,AndroidPermissionUsage,AndroidPrivacyAppDataSharingUpdates,AndroidPrivacyControls,AndroidWorkPolicyInfo</string>
+ <!-- Comma separated list of safety source IDs to add an Intent Extra confirming they should be displayed as if opened by a settings UI page. -->
+ <string name="config_useSettingsHomepageIntentExtra" translatable="false">AndroidMoreSettings,AndroidPrivateSpace,TestSource</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-v35/strings.xml b/SafetyCenter/Resources/res/values-v35/strings.xml
new file mode 100644
index 000000000..620dc8d60
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-v35/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- More settings -->
+ <string name="private_space_title" description="The title of the entry for Private Space">Private Space</string>
+ <string name="private_space_summary" description="The summary of the entry for Private Space settings, which describes the page contents">Setup Private Space, and more</string>
+ <string name="private_space_search_terms" description="Search keywords of the entry for Private Space settings">Private Space</string>
+
+</resources>
diff --git a/SafetyCenter/Resources/res/values-vi-v34/strings.xml b/SafetyCenter/Resources/res/values-vi-v34/strings.xml
index 473a3db59..c4b5ad44f 100644
--- a/SafetyCenter/Resources/res/values-vi-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-vi-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Sức khoẻ, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Cập nhật chế độ Chia sẻ dữ liệu vị trí"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Dữ liệu, tính năng Chia sẻ dữ liệu, cập nhật chế độ Chia sẻ dữ liệu, cập nhật chế độ Chia sẻ dữ liệu vị trí, chia sẻ"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Quyền riêng tư trong quảng cáo"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Tuỳ chỉnh thông tin được các ứng dụng dùng để hiển thị quảng cáo cho bạn"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"quảng cáo, quyền riêng tư trong quảng cáo, hộp cát về quyền riêng tư, chủ đề quảng cáo, quảng cáo do ứng dụng gợi ý, đo lường quảng cáo"</string>
<string name="advanced_title" msgid="6259362998269627310">"Chế độ cài đặt khác"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Các chế độ khác về bảo mật và quyền riêng tư"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Tự động điền, thông báo và nhiều chế độ cài đặt khác"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Thông tin về chính sách của nơi bạn làm việc"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-vi-v35/strings.xml b/SafetyCenter/Resources/res/values-vi-v35/strings.xml
new file mode 100644
index 000000000..b37e81085
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-vi-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Không gian riêng tư"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Thiết lập Không gian riêng tư và các tính năng khác"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Không gian riêng tư"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-vi/strings.xml b/SafetyCenter/Resources/res/values-vi/strings.xml
index 1a1b22ccc..e121cad41 100644
--- a/SafetyCenter/Resources/res/values-vi/strings.xml
+++ b/SafetyCenter/Resources/res/values-vi/strings.xml
@@ -37,7 +37,7 @@
<string name="privacy_controls_summary" msgid="2402066941190435424">"Kiểm soát quyền truy cập của thiết bị vào micrô, máy ảnh và nhiều ứng dụng khác"</string>
<string name="privacy_controls_search_terms" msgid="3774472175934304165">"Quyền riêng tư, Chế độ kiểm soát quyền riêng tư"</string>
<string name="advanced_title" msgid="8745436380690561172">"Chế độ cài đặt khác"</string>
- <string name="advanced_security_title" msgid="1126833338772188155">"Các chế độ cài đặt bảo mật khác"</string>
+ <string name="advanced_security_title" msgid="1126833338772188155">"Chế độ cài đặt bảo mật khác"</string>
<string name="advanced_security_summary" msgid="6172253327022425123">"Mã hoá, thông tin xác thực và các chế độ cài đặt khác"</string>
<string name="advanced_security_search_terms" msgid="3350609555814362075"></string>
<string name="advanced_privacy_title" msgid="1117725225706176643">"Các chế độ cài đặt quyền riêng tư khác"</string>
diff --git a/SafetyCenter/Resources/res/values-zh-rCN-v34/strings.xml b/SafetyCenter/Resources/res/values-zh-rCN-v34/strings.xml
index 4109e8228..5b8a8fe8d 100644
--- a/SafetyCenter/Resources/res/values-zh-rCN-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rCN-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"健康, Health, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"位置数据分享方面的更新"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"数据, 数据分享, 数据分享方面的更新, 位置数据分享方面的更新, 分享, Data, Data sharing, Data sharing updates, Data sharing updates for location, sharing"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"广告隐私权"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"自定义应用可以使用哪些信息来向您展示广告"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"广告, 广告隐私权, Privacy Sandbox, 广告主题, 应用建议的广告, 广告衡量, ads, ad privacy, privacy sandbox, ad topics, app-suggested ads, ad measurement"</string>
<string name="advanced_title" msgid="6259362998269627310">"其他设置"</string>
- <string name="more_settings_title" msgid="9033454654010697185">"更多安全性和隐私权设置"</string>
+ <string name="more_settings_title" msgid="9033454654010697185">"更多安全和隐私设置"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"自动填充、通知等"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"您的工作政策信息"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml
new file mode 100644
index 000000000..e13cffd8a
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"私密空间"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"设置私密空间等"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"私密空间"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rHK-v34/strings.xml b/SafetyCenter/Resources/res/values-zh-rHK-v34/strings.xml
index 1d27b164c..a11abbde1 100644
--- a/SafetyCenter/Resources/res/values-zh-rHK-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rHK-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"健康, Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"位置資料分享更新"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"資料, 資料分享, 資料分享更新, 位置資料分享更新, 分享"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"廣告私隱權"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"自訂應用程式根據哪些資料向您顯示廣告"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"廣告, 廣告私隱權, 私隱沙箱, 廣告主題, 應用程式建議廣告, 廣告評估功能"</string>
<string name="advanced_title" msgid="6259362998269627310">"其他設定"</string>
<string name="more_settings_title" msgid="9033454654010697185">"更多安全性和私隱權設定"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"自動填入、通知等"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"你的工作政策資料"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml
new file mode 100644
index 000000000..996efe5f3
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"私人空間"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"設定「私人空間」等項目"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"私人空間"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rTW-v34/strings.xml b/SafetyCenter/Resources/res/values-zh-rTW-v34/strings.xml
index 4c00d5c77..288a0566c 100644
--- a/SafetyCenter/Resources/res/values-zh-rTW-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rTW-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"健康、Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"位置資料分享更新"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"資料, 資料分享, 資料分享更新, 位置資料分享更新, 分享"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"廣告隱私權"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"自訂應用程式可用來放送廣告的資訊"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"廣告, 廣告隱私權, Privacy Sandbox, 廣告主題, 應用程式建議廣告, 廣告評估"</string>
<string name="advanced_title" msgid="6259362998269627310">"其他設定"</string>
<string name="more_settings_title" msgid="9033454654010697185">"其他安全性和隱私權設定"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"自動填入、通知等等"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"公司政策資訊"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml
new file mode 100644
index 000000000..36f68819d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"私人空間"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"設定私人空間等項目"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"私人空間"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values-zu-v34/strings.xml b/SafetyCenter/Resources/res/values-zu-v34/strings.xml
index d7c75a0a8..d5c86c668 100644
--- a/SafetyCenter/Resources/res/values-zu-v34/strings.xml
+++ b/SafetyCenter/Resources/res/values-zu-v34/strings.xml
@@ -24,11 +24,9 @@
<string name="health_connect_search_terms" msgid="4998970586245680829">"Impilo, i-Health Connect"</string>
<string name="app_data_sharing_updates_title" msgid="7428862330643262588">"Izibuyekezo zokwabelana ngedatha zendawo"</string>
<string name="app_data_sharing_updates_search_terms" msgid="8414777373734245398">"Idatha, Ukwabelana ngedatha, Izibuyekezo zokwabelana ngedatha, Izibuyekezo zokwabelana ngedatha zendawo, ukwabelana"</string>
- <string name="ads_privacy_title" msgid="2478678200445158640">"Ubumfihlo besikhangiso"</string>
- <string name="ads_privacy_summary" msgid="4977699525670966049">"Enza ngokwezifiso ama-app asetshenziswayo ukukubonisa izikhangiso"</string>
- <string name="ads_privacy_search_terms" msgid="8008413316055240046">"izikhangiso, ubumfihlo bezikhangiso, i-sandbox yobumfihlo, izihloko zesikhangiso, izikhangiso zeziphakamiso ze-app, ukukalwa kwesikhangiso"</string>
<string name="advanced_title" msgid="6259362998269627310">"Amanye amasethingi"</string>
<string name="more_settings_title" msgid="9033454654010697185">"Ukuvikeleka okwengeziwe nobumfihlo"</string>
<string name="more_settings_summary" msgid="7086620830002515710">"Ukugcwalisa okuzenzekelayo, isaziso, nokuningi"</string>
<string name="more_settings_search_terms" msgid="1371913937610933955"></string>
+ <string name="work_policy_title" msgid="915692932391542104">"Ulwazi lwenqubomgomo yakho yomsebenzi"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-zu-v35/strings.xml b/SafetyCenter/Resources/res/values-zu-v35/strings.xml
new file mode 100644
index 000000000..659e1b58d
--- /dev/null
+++ b/SafetyCenter/Resources/res/values-zu-v35/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="private_space_title" msgid="6158245041481535879">"Isikhala Esiyimfihlo"</string>
+ <string name="private_space_summary" msgid="529869826714610294">"Setha Isikhala Esiyimfihlo, nokunye"</string>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Isikhala Esiyimfihlo"</string>
+</resources>
diff --git a/SafetyCenter/Resources/res/values/config.xml b/SafetyCenter/Resources/res/values/config.xml
index 6b20b69b4..2c92afb21 100644
--- a/SafetyCenter/Resources/res/values/config.xml
+++ b/SafetyCenter/Resources/res/values/config.xml
@@ -22,4 +22,6 @@
<string name="config_NotificationListenerServicePregrants" translatable="false"></string>
<!-- Comma separated list of safety source IDs to add an Intent Extra confirming they should be displayed as if opened by a settings UI page. -->
<string name="config_useSettingsHomepageIntentExtra" translatable="false">AndroidAdvancedPrivacy,AndroidAdvancedSecurity,TestSource</string>
+ <!-- Comma separated list of safety source IDs that should be refreshed on page open by default. -->
+ <string name="config_defaultRefreshOnPageOpenSources" translatable="false"></string>
</resources>
diff --git a/SafetyCenter/Resources/shared_res/values-af/strings.xml b/SafetyCenter/Resources/shared_res/values-af/strings.xml
index 74ecafb6c..3c20c6428 100644
--- a/SafetyCenter/Resources/shared_res/values-af/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-af/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skandeer tans"</string>
<string name="loading_summary" msgid="3740846439782713910">"Gaan tans toestelinstellings na …"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Lyk goed"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Geen probleme gevind nie"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Wenk beskikbaar}other{Wenke beskikbaar}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Geen kwessies is gekry nie"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Sien aanbeveling}other{Sien aanbevelings}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Handeling uitgevoer}other{Handelinge uitgevoer}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Gaan instellings na"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Gaan instellingslys na"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potensiële risiko’s gevind"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risiko’s gevind"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Rekening is dalk in gevaar"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Rekening is in gevaar"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Sien waarskuwing hieronder}other{Sien waarskuwings hieronder}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Rekening is in gevaar"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Sien waarskuwing}other{Sien waarskuwings}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Kon nie bladsy oopmaak nie"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Kon nie opletberig afhandel nie"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Kon nie instellings herlaai nie"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Kon nie instelling nagaan nie}other{Kon nie instellings nagaan nie}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Werkprofiel is onderbreek"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Nog geen inligting nie"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-am/strings.xml b/SafetyCenter/Resources/shared_res/values-am/strings.xml
index 0e123315a..d1080ebf7 100644
--- a/SafetyCenter/Resources/shared_res/values-am/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-am/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"በመቃኘት ላይ"</string>
<string name="loading_summary" msgid="3740846439782713910">"የመሣሪያ ቅንብሮችን በመፈተሽ ላይ…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ጥሩ ይመስላል"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ምንም ችግሮች አልተገኙም"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ጠቃሚ ምክር ይገኛል}one{ጠቃሚ ምክር ይገኛል}other{ጠቃሚ ምክሮች ይገኛሉ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ምንም ችግሮች አልተገኙም"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ምክር ይመልከቱ}one{ምክር ይመልከቱ}other{ምክሮችን ይመልከቱ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{የተወሰደ እርምጃ}one{የተወሰደ እርምጃ}other{የተወሰዱ እርምጃዎች}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ቅንብሮችን ይከልሱ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"የቅንብሮች ዝርዝርን ይፈትሹ"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ሊከሰቱ የሚችሉ አደጋዎች ተገኝተዋል"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"አደጋዎች ተገኝተዋል"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"መለያ አደጋ ላይ ሊሆን ይችላል"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"መለያ አደጋ ላይ ነው"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ማንቂያን ከታች ይመልከቱ}one{ማንቂያን ከታች ይመልከቱ}other{ማንቂያዎችን ከታች ይመልከቱ}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"መለያ አደጋ ላይ ነው"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ማንቂያ ይመልከቱ}one{ማንቂያ ይመልከቱ}other{ማንቂያዎች ይመልከቱ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ገጹን መከፈት አልተቻለም"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ማንቂያን መፍታት አልተቻለም"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ቅንብሮችን ማደስ አልተቻለም"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ቅንብርን መፈተሽ አልተቻለም}one{ቅንብርን መፈተሽ አልተቻለም}other{ቅንብሮችን መፈተሽ አልተቻለም}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"የስራ መገለጫ ባለበት ቆሟል"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ገና ምንም መረጃ የለም"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ar/strings.xml b/SafetyCenter/Resources/shared_res/values-ar/strings.xml
index c83c5d713..49e16c39c 100644
--- a/SafetyCenter/Resources/shared_res/values-ar/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ar/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"جارٍ الفحص"</string>
<string name="loading_summary" msgid="3740846439782713910">"جارٍ التحقّق من إعدادات الجهاز…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"كل شيء على ما يرام"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"لم يتم العثور على أي مشاكل"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{تتوفّر نصيحة.}zero{تتوفّر نصائح.}two{تتوفّر نصيحتان.}few{تتوفّر نصائح.}many{تتوفّر نصائح.}other{تتوفّر نصائح.}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"لم يتم رصد أي مشاكل."</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{الاطّلاع على اقتراح}zero{الاطّلاع على اقتراحات}two{الاطّلاع على اقتراحَين}few{الاطّلاع على اقتراحات}many{الاطّلاع على اقتراحات}other{الاطّلاع على اقتراحات}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{الإجراء الذي تم اتخاذه}zero{الإجراءات التي تم اتخاذها}two{الإجراءان اللذان تم اتخاذهما}few{الإجراءات التي تم اتخاذها}many{الإجراءات التي تم اتخاذها}other{الإجراءات التي تم اتخاذها}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"مراجعة الإعدادات"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"الاطّلاع على قائمة الإعدادات"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"هناك مخاطر محتملة"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"هناك مخاطر"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"قد يكون الحساب معرّضًا للخطر"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"الحساب معرّض للخطر"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{راجِع التنبيه أدناه.}zero{راجِع التنبيهات أدناه.}two{راجِع التنبيهَين أدناه.}few{راجِع التنبيهات أدناه.}many{راجِع التنبيهات أدناه.}other{راجِع التنبيهات أدناه.}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"الحساب معرّض للخطر"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{الاطّلاع على التنبيه}zero{الاطّلاع على التنبيهات}two{الاطّلاع على التنبيهَين}few{الاطّلاع على التنبيهات}many{الاطّلاع على التنبيهات}other{الاطّلاع على التنبيهات}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"تعذَّر فتح الصفحة"</string>
<string name="resolving_action_error" msgid="371968886143262375">"تعذَّر التعامل بشكل نهائي مع التنبيه"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"تعذّر تحديث الإعدادات"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{تعذّر التحقّق من الإعداد.}zero{تعذّر التحقّق من الإعدادات.}two{تعذّر التحقّق من الإعدادَين.}few{تعذّر التحقّق من الإعدادات.}many{تعذّر التحقّق من الإعدادات.}other{تعذّر التحقّق من الإعدادات.}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"تم إيقاف الملف الشخصي للعمل مؤقتًا"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ما مِن معلومات بعد."</string>
diff --git a/SafetyCenter/Resources/shared_res/values-as/strings.xml b/SafetyCenter/Resources/shared_res/values-as/strings.xml
index 90ae9c5c2..4105c26d0 100644
--- a/SafetyCenter/Resources/shared_res/values-as/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-as/strings.xml
@@ -19,9 +19,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"স্কেন কৰি থকা হৈছে"</string>
<string name="loading_summary" msgid="3740846439782713910">"ডিভাইচৰ ছেটিং পৰীক্ষা কৰি থকা হৈছে…"</string>
- <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ভাল যেন লাগিছে"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"কোনো সমস্যা পোৱা নগ’ল"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{পৰামৰ্শ উপলব্ধ}one{পৰামৰ্শ উপলব্ধ}other{পৰামৰ্শ উপলব্ধ}}"</string>
+ <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ঠিকেই লাগিছে"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"কোনো সমস্যা পোৱা নগ’ল"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{চুপাৰিছ চাওক}one{চুপাৰিছসমূহ চাওক}other{চুপাৰিছসমূহ চাওক}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{কাৰ্যব্যৱস্থা লোৱা হৈছে}one{কাৰ্যব্যৱস্থা লোৱা হৈছে}other{কাৰ্যব্যৱস্থা লোৱা হৈছে}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ছেটিং পৰ্যালোচনা কৰক"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ছেটিঙৰ সূচী পৰীক্ষা কৰক"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"সম্ভাব্য বিপদাশংকা পোৱা গৈছে"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"বিপদাশংকা পোৱা গৈছে"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"একাউণ্টটোত বিপদাশংকা থাকিব পাৰে"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"একাউণ্টৰ বিপদাশংকা আছে"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{তলত সতৰ্কবাৰ্তা চাওক}one{তলত সতৰ্কবাৰ্তা চাওক}other{তলত সতৰ্কবাৰ্তা চাওক}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"একাউণ্টটোত বিপদাশংকা আছে"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{সতৰ্কবাৰ্তা চাওক}one{সতৰ্কবাৰ্তাসমূহ চাওক}other{সতৰ্কবাৰ্তাসমূহ চাওক}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"পৃষ্ঠাখন খুলিব পৰা নগ’ল"</string>
<string name="resolving_action_error" msgid="371968886143262375">"সতৰ্কবাৰ্তা সমাধান কৰিব পৰা নগ’ল"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ছেটিং ৰিফ্ৰেশ্ব কৰিব পৰা নগ’ল"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ছেটিং পৰীক্ষা কৰিব পৰা নগ’ল}one{ছেটিং পৰীক্ষা কৰিব পৰা নগ’ল}other{ছেটিং পৰীক্ষা কৰিব পৰা নগ’ল}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"কৰ্মস্থানৰ প্ৰ’ফাইলটো পজ কৰা আছে"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"এতিয়ালৈকে কোনো তথ্য নাই"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-az/strings.xml b/SafetyCenter/Resources/shared_res/values-az/strings.xml
index a9c7e92ae..7e2e7c140 100644
--- a/SafetyCenter/Resources/shared_res/values-az/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-az/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skan edilir"</string>
<string name="loading_summary" msgid="3740846439782713910">"Cihaz ayarları yoxlanılır…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Yaxşı görünür"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Heç bir problem tapılmadı"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{İpucu əlçatandır}other{İpucları əlçatandır}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Problem tapılmadı"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Tövsiyəyə baxın}other{Tövsiyələrə baxın}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Görülən tədbir}other{Görülən tədbirlər}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Ayarları nəzərdən keçirin"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Ayarlar siyahısını yoxlayın"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potensial risklər tapıldı"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risklər tapıldı"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Hesab risk altında ola bilər"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Hesab risk altındadır"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Aşağıdakı siqnala baxın}other{Aşağıdakı siqnallara baxın}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Hesab risk altındadır"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Xəbərdarlığa baxın}other{Xəbərdarlıqlara baxın}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Səhifəni açmaq mümkün olmadı"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Siqnalı həll etmək mümkün olmadı"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Ayarları yeniləmək mümkün olmadı"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Ayarı yoxlamaq alınmadı}other{Ayarları yoxlamaq alınmadı}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"İş profili durdurulub"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Hələ ki, məlumat yoxdur"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-b+sr+Latn/strings.xml b/SafetyCenter/Resources/shared_res/values-b+sr+Latn/strings.xml
index 2ce59e648..19660cb06 100644
--- a/SafetyCenter/Resources/shared_res/values-b+sr+Latn/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-b+sr+Latn/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skenira se"</string>
<string name="loading_summary" msgid="3740846439782713910">"Proveravamo podešavanja uređaja…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Sve je u redu"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nije pronađen nijedan problem"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Dostupan je savet}one{Dostupni su saveti}few{Dostupni su saveti}other{Dostupni su saveti}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nije pronađen nijedan problem"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Prikaži preporuku}one{Prikaži preporuke}few{Prikaži preporuke}other{Prikaži preporuke}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Preduzeta radnja}one{Preduzete radnje}few{Preduzete radnje}other{Preduzete radnje}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Pregledajte podešavanja"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Proverite listu podešavanja"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Pronađeni su potencijalni rizici"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Pronađeni su rizici"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Nalog je možda ugrožen"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Nalog je ugrožen"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Pogledajte upozorenje ispod}one{Pogledajte upozorenja ispod}few{Pogledajte upozorenja ispod}other{Pogledajte upozorenja ispod}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Nalog je ugrožen"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Prikaži obaveštenje}one{Prikaži obaveštenja}few{Prikaži obaveštenja}other{Prikaži obaveštenja}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Otvaranje stranice nije uspelo"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Rešavanje obaveštenja nije uspelo"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Osvežavanje podešavanja nije uspelo"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Provera podešavanja nije uspela}one{Provera podešavanja nije uspela}few{Provera podešavanja nije uspela}other{Provera podešavanja nije uspela}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Poslovni profil je pauziran"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Još nema informacija"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-be/strings.xml b/SafetyCenter/Resources/shared_res/values-be/strings.xml
index 5dfc83cc5..2c27670e4 100644
--- a/SafetyCenter/Resources/shared_res/values-be/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-be/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Выконваецца праверка"</string>
<string name="loading_summary" msgid="3740846439782713910">"Праверка налад прылады…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Усё ў парадку"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Праблемы не знойдзены"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Скарыстайце параду}one{Скарыстайце парады}few{Скарыстайце парады}many{Скарыстайце парады}other{Скарыстайце парады}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Праблем не знойдзена"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Паглядзець рэкамендацыю}one{Паглядзець рэкамендацыі}few{Паглядзець рэкамендацыі}many{Паглядзець рэкамендацыі}other{Паглядзець рэкамендацыі}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Мера прынята}one{Меры прыняты}few{Меры прыняты}many{Меры прыняты}other{Меры прыняты}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Праглядзець налады"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Праверыць спіс налад"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Выяўлена патэнцыяльная небяспека"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Выяўлена небяспека"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Уліковы запіс можа быць у небяспецы"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Уліковы запіс у небяспецы"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Глядзіце апавяшчэнне ніжэй}one{Глядзіце апавяшчэнні ніжэй}few{Глядзіце апавяшчэнні ніжэй}many{Глядзіце апавяшчэнні ніжэй}other{Глядзіце апавяшчэнні ніжэй}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Уліковы запіс у небяспецы"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Паглядзець абвестку}one{Паглядзець абвесткі}few{Паглядзець абвесткі}many{Паглядзець абвесткі}other{Паглядзець абвесткі}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Не ўдалося адкрыць старонку"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Не ўдалося вырашыць праблему"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Не ўдалося абнавіць налады"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Не ўдалося праверыць наладу}one{Не ўдалося праверыць налады}few{Не ўдалося праверыць налады}many{Не ўдалося праверыць налады}other{Не ўдалося праверыць налады}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Працоўны профіль прыпынены"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Пакуль няма інфармацыі"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-bg/strings.xml b/SafetyCenter/Resources/shared_res/values-bg/strings.xml
index 74c581599..e3495d4d5 100644
--- a/SafetyCenter/Resources/shared_res/values-bg/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-bg/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Сканиране"</string>
<string name="loading_summary" msgid="3740846439782713910">"Настройките на устройството се проверяват…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Изглежда добре"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Няма открити проблеми"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Налице е съвет}other{Налице са съвети}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Няма открити проблеми"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Преглед на препоръката}other{Преглед на препоръките}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Предприето е действие}other{Предприети са действия}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Преглед на настройките"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Проверка на списъка с настройки"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Открити са потенциални рискове"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Открити са рискове"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Профилът може да е изложен на риск"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Профилът е изложен на риск"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Вижте сигнала по-долу}other{Вижте сигналите по-долу}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Профилът е изложен на риск"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Преглед на сигнала}other{Преглед на сигналите}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Страницата не се отвори"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Сигналът не се отстрани"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Настройките не бяха опреснени"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Настройката не бе проверена}other{Настройките не бяха проверени}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Служебният потребителски профил е поставен на пауза"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Още няма информация"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-bn/strings.xml b/SafetyCenter/Resources/shared_res/values-bn/strings.xml
index 99a2205b9..3f24f05a4 100644
--- a/SafetyCenter/Resources/shared_res/values-bn/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-bn/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"স্ক্যান করা হচ্ছে"</string>
<string name="loading_summary" msgid="3740846439782713910">"ডিভাইস সেটিংস চেক করা হচ্ছে…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"সব ঠিক আছে"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"কোনও সমস্যা পাওয়া যায়নি"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{পরামর্শ উপলভ্য আছে}one{পরামর্শ উপলভ্য আছে}other{পরামর্শ উপলভ্য আছে}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"কোনও সমস্যা পাওয়া যায়নি"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{সাজেশন দেখুন}one{সাজেশন দেখুন}other{সাজেশন দেখুন}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{অ্যাকশন নেওয়া হয়েছে}one{অ্যাকশন নেওয়া হয়েছে}other{অ্যাকশন নেওয়া হয়েছে}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"সেটিংস পর্যালোচনা করুন"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"সেটিংস তালিকা চেক করুন"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"সম্ভাব্য ঝুঁকি খুঁজে পাওয়া গেছে"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ঝুঁকির বিষয়টি খুঁজে পাওয়া গেছে"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"অ্যাকাউন্টের হয়ত ক্ষতি হতে পারে"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"অ্যাকাউন্টের ক্ষতি হতে পারে"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{নিচে সতর্কতা দেখুন}one{নিচে সতর্কতা দেখুন}other{নিচে সতর্কতা দেখুন}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"অ্যাকাউন্ট সুরক্ষিত নয়"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{বিজ্ঞপ্তি দেখুন}one{বিজ্ঞপ্তি দেখুন}other{বিজ্ঞপ্তি দেখুন}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"পৃষ্ঠা খোলা যায়নি"</string>
<string name="resolving_action_error" msgid="371968886143262375">"সতর্কতার সমাধান করা যায়নি"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"সেটিংস রিফ্রেশ করা যায়নি"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{সেটিং চেক করা যায়নি}one{সেটিংস চেক করা যায়নি}other{সেটিংস চেক করা যায়নি}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"অফিস প্রোফাইল পজ করা আছে"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"এখনও কোনও তথ্য নেই"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-bs/strings.xml b/SafetyCenter/Resources/shared_res/values-bs/strings.xml
index 3b53a5b00..a877f8b36 100644
--- a/SafetyCenter/Resources/shared_res/values-bs/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-bs/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skeniranje"</string>
<string name="loading_summary" msgid="3740846439782713910">"Provjera postavki uređaja…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Izgleda dobro"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nije pronađen nijedan problem"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Savjet je dostupan}one{Savjeti su dostupni}few{Savjeti su dostupni}other{Savjeti su dostupni}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nije pronađen nijedan problem"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Pogledajte preporuku}one{Pogledajte preporuke}few{Pogledajte preporuke}other{Pogledajte preporuke}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Poduzeta ja radnja}one{Poduzete su radnje}few{Poduzete su radnje}other{Poduzete su radnje}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Pregledajte postavke"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Provjerite listu postavki"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Pronađeni su potencijalni rizici"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Pronađeni su rizici"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Račun bi mogao biti izložen riziku"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Račun je izložen riziku"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Pogledajte upozorenje u nastavku}one{Pogledajte upozorenja u nastavku}few{Pogledajte upozorenja u nastavku}other{Pogledajte upozorenja u nastavku}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Račun je izložen riziku"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Pogledajte upozorenje}one{Pogledajte upozorenja}few{Pogledajte upozorenja}other{Pogledajte upozorenja}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Otvaranje stranice nije uspjelo"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Rješavanje upozorenja nije uspjelo"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Osvježavanje postavki nije uspjelo"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Provjera postavke nije uspjela}one{Provjera postavki nije uspjela}few{Provjera postavki nije uspjela}other{Provjera postavki nije uspjela}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Radni profil je pauziran"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Još uvijek nema informacija"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ca/strings.xml b/SafetyCenter/Resources/shared_res/values-ca/strings.xml
index 46e395667..640a723c1 100644
--- a/SafetyCenter/Resources/shared_res/values-ca/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ca/strings.xml
@@ -20,13 +20,13 @@
<string name="scanning_title" msgid="5424849039854311398">"S\'està analitzant"</string>
<string name="loading_summary" msgid="3740846439782713910">"S\'està comprovant la configuració del dispositiu…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tot correcte"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No s\'ha trobat cap problema"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Hi ha un consell disponible}many{Hi ha consells disponibles}other{Hi ha consells disponibles}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No s\'ha trobat cap problema"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Mostra la recomanació}many{Mostra les recomanacions}other{Mostra les recomanacions}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{S\'ha dut a terme una acció}many{S\'han dut a terme accions}other{S\'han dut a terme accions}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisa la configuració"</string>
- <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Comprova la llista de configuració"</string>
+ <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Comprova la llista d\'opcions de configuració"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"El dispositiu pot estar en perill"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"El dispositiu està en perill"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Dispositiu en perill"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"Les dades poden estar en perill"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"Les dades estan en perill"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"Contrasenyes en perill (antigues)"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"S\'han trobat possibles riscos"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"S\'han trobat riscos"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"El compte pot estar en perill"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Aquest compte està en perill"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Revisa l\'alerta següent}many{Revisa les alertes següents}other{Revisa les alertes següents}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"El compte està en perill"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Mostra l\'alerta}many{Mostra les alertes}other{Mostra les alertes}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"No s\'ha pogut obrir la pàgina"</string>
<string name="resolving_action_error" msgid="371968886143262375">"No s\'ha pogut resoldre l\'alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"No s\'ha pogut actualitzar la configuració"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{No s\'ha pogut comprovar la configuració}many{No s\'ha pogut comprovar la configuració}other{No s\'ha pogut comprovar la configuració}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"El perfil de treball s\'ha posat en pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Encara no hi ha informació"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-cs/strings.xml b/SafetyCenter/Resources/shared_res/values-cs/strings.xml
index ef97185fb..28aabd4e8 100644
--- a/SafetyCenter/Resources/shared_res/values-cs/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-cs/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Probíhá kontrola"</string>
<string name="loading_summary" msgid="3740846439782713910">"Kontrola nastavení zařízení…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Všechno v pořádku"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nebyly nalezeny žádné problémy"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Je k dispozici tip}few{Jsou k dispozici tipy}many{Jsou k dispozici tipy}other{Jsou k dispozici tipy}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nebyly zjištěny žádné problémy"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Zobrazit doporučení}few{Zobrazit doporučení}many{Zobrazit doporučení}other{Zobrazit doporučení}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Bylo přijato opatření}few{Byla přijata opatření}many{Byla přijata opatření}other{Byla přijata opatření}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Zkontrolujte nastavení"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Zkontrolujte seznam nastavení"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Byla nalezena možná rizika"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Byla nalezena rizika"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Účet může být ohrožen"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Účet je ohrožen"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Přečtěte si upozornění níže}few{Přečtěte si upozornění níže}many{Přečtěte si upozornění níže}other{Přečtěte si upozornění níže}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Účet je ohrožen"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Zobrazit upozornění}few{Zobrazit upozornění}many{Zobrazit upozornění}other{Zobrazit upozornění}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Stránku nelze otevřít"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Upozornění se nepodařilo vyřešit"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nastavení se nepodařilo obnovit"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nastavení nelze zkontrolovat}few{Nastavení nelze zkontrolovat}many{Nastavení nelze zkontrolovat}other{Nastavení nelze zkontrolovat}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Pracovní profil je pozastaven"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Zatím žádné údaje"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-da/strings.xml b/SafetyCenter/Resources/shared_res/values-da/strings.xml
index 1903c2a23..e4d28aaf1 100644
--- a/SafetyCenter/Resources/shared_res/values-da/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-da/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scanner"</string>
<string name="loading_summary" msgid="3740846439782713910">"Tjekker enheds­indstillinger…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Det ser fint ud"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Der blev ikke fundet nogen problemer"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Der er et tilgængeligt tip}one{Der er et tilgængeligt tip}other{Der er tilgængelige tips}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Der blev ikke fundet nogen problemer"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Se anbefaling}one{Se anbefaling}other{Se anbefalinger}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{En handling er udført}one{En handling er udført}other{Handlinger er udført}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Gennemgå indstillingerne"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Tjek listen over indstillinger"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Der blev fundet potentielle risici"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Der blev fundet risici"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Kontoen kan være sårbar"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Kontoen er sårbar"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Se underretningen nedenfor}one{Se underretningen nedenfor}other{Se underretningerne nedenfor}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Kontoen er sårbar"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Se underretning}one{Se underretning}other{Se underretninger}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Siden kunne ikke åbnes"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Underretningen kunne ikke behandles"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Indstillingerne kunne ikke opdateres"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Indstillingen kunne ikke tjekkes}one{Indstillingen kunne ikke tjekkes}other{Indstillingerne kunne ikke tjekkes}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Arbejdsprofilen er sat på pause"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Der er ingen oplysninger endnu"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-de/strings.xml b/SafetyCenter/Resources/shared_res/values-de/strings.xml
index d3777c6c9..a5b1758ad 100644
--- a/SafetyCenter/Resources/shared_res/values-de/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-de/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scan wird ausgeführt"</string>
<string name="loading_summary" msgid="3740846439782713910">"Ge­räte­ein­stel­lungen wer­den ge­prüft…­"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Alles in Ordnung"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Keine Probleme gefunden"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tipp verfügbar}other{Tipps verfügbar}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Keine Probleme gefunden"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Empfehlung ansehen}other{Empfehlungen ansehen}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Maßnahme ergriffen}other{Maßnahmen ergriffen}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Einstellungen prüfen"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Liste der Einstellungen prüfen"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Mögliche Sicherheitsrisiken gefunden"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Sicherheitsrisiken gefunden"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Konto eventuell gefährdet"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Konto gefährdet"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Benachrichtigung unten ansehen}other{Benachrichtigungen unten ansehen}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Konto ist gefährdet"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Benachrichtigung ansehen}other{Benachrichtigungen ansehen}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Seite konnte nicht geöffnet werden"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Ursache konnte nicht behoben werden"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Einstellungen konnten nicht aktualisiert werden"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Einstellung konnte nicht überprüft werden}other{Einstellungen konnten nicht überprüft werden}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Arbeitsprofil pausiert"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Noch keine Angaben vorhanden"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-el/strings.xml b/SafetyCenter/Resources/shared_res/values-el/strings.xml
index 194ce7b43..c6f005d5f 100644
--- a/SafetyCenter/Resources/shared_res/values-el/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-el/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Σάρωση"</string>
<string name="loading_summary" msgid="3740846439782713910">"Έλεγχος ρυθμίσεων συσκευής…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Όλα εντάξει"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Δεν εντοπίστηκαν προβλήματα"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Διαθέσιμη συμβουλή}other{Διαθέσιμες συμβουλές}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Δεν βρέθηκαν προβλήματα"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Εμφάνιση πρότασης}other{Εμφάνιση προτάσεων}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ενέργεια που εκτελέστηκε}other{Ενέργειες που εκτελέστηκαν}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Έλεγχος ρυθμίσεων"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Έλεγχος λίστας ρυθμίσεων"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Εντοπίστηκαν πιθανοί κίνδυνοι"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Εντοπίστηκαν κίνδυνοι"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Ο λογαριασμός μπορεί να κινδυνεύει"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Ο λογαριασμός βρίσκεται σε κίνδυνο"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Δείτε την παρακάτω ειδοποίηση}other{Δείτε τις παρακάτω ειδοποιήσεις}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Ο λογαριασμός κινδυνεύει"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Εμφάνιση ειδοποίησης}other{Εμφάνιση ειδοποιήσεων}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Δεν ήταν δυνατό το άνοιγμα της σελίδας"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Δεν ήταν δυνατή η επίλυση της ειδοποίησης"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Δεν ήταν δυνατή η ανανέωση των ρυθμίσεων"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Δεν ήταν δυνατός ο έλεγχος της ρύθμισης}other{Δεν ήταν δυνατός ο έλεγχος των ρυθμίσεων}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Το προφίλ εργασίας έχει τεθεί σε παύση"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Δεν υπάρχουν ακόμα πληροφορίες"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-en-rAU/strings.xml b/SafetyCenter/Resources/shared_res/values-en-rAU/strings.xml
index 30a550534..f389be966 100644
--- a/SafetyCenter/Resources/shared_res/values-en-rAU/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-en-rAU/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scanning"</string>
<string name="loading_summary" msgid="3740846439782713910">"Checking device settings…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Looks fine"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No problems found"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tip available}other{Tips available}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No issues found"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{See recommendation}other{See recommendations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Action taken}other{Actions taken}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Review settings"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Check settings list"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potential risks found"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risks found"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Account may be at risk"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Account is at risk"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{See alert below}other{See alerts below}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account at risk"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{See alert}other{See alerts}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Couldn\'t open page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Couldn\'t resolve alert"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Couldn\'t refresh settings"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Couldn\'t check setting}other{Couldn\'t check settings}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Work profile is paused"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"No info yet"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-en-rCA/strings.xml b/SafetyCenter/Resources/shared_res/values-en-rCA/strings.xml
index de95f0bd0..00234beca 100644
--- a/SafetyCenter/Resources/shared_res/values-en-rCA/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-en-rCA/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scanning"</string>
<string name="loading_summary" msgid="3740846439782713910">"Checking device settings…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Looks good"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No problems found"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tip available}other{Tips available}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No issues found"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{See recommendation}other{See recommendations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Action taken}other{Actions taken}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Review settings"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Check settings list"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potential risks found"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risks found"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Account may be at risk"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Account is at risk"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{See alert below}other{See alerts below}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account at risk"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{See alert}other{See alerts}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Couldnt open page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Couldnt resolve alert"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Couldnt refresh settings"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Couldnt check setting}other{Couldnt check settings}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Work profile is paused"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"No info yet"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-en-rGB/strings.xml b/SafetyCenter/Resources/shared_res/values-en-rGB/strings.xml
index 30a550534..f389be966 100644
--- a/SafetyCenter/Resources/shared_res/values-en-rGB/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-en-rGB/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scanning"</string>
<string name="loading_summary" msgid="3740846439782713910">"Checking device settings…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Looks fine"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No problems found"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tip available}other{Tips available}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No issues found"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{See recommendation}other{See recommendations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Action taken}other{Actions taken}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Review settings"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Check settings list"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potential risks found"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risks found"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Account may be at risk"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Account is at risk"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{See alert below}other{See alerts below}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account at risk"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{See alert}other{See alerts}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Couldn\'t open page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Couldn\'t resolve alert"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Couldn\'t refresh settings"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Couldn\'t check setting}other{Couldn\'t check settings}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Work profile is paused"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"No info yet"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-en-rIN/strings.xml b/SafetyCenter/Resources/shared_res/values-en-rIN/strings.xml
index 30a550534..f389be966 100644
--- a/SafetyCenter/Resources/shared_res/values-en-rIN/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-en-rIN/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Scanning"</string>
<string name="loading_summary" msgid="3740846439782713910">"Checking device settings…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Looks fine"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No problems found"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tip available}other{Tips available}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No issues found"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{See recommendation}other{See recommendations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Action taken}other{Actions taken}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Review settings"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Check settings list"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potential risks found"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risks found"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Account may be at risk"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Account is at risk"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{See alert below}other{See alerts below}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account at risk"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{See alert}other{See alerts}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Couldn\'t open page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Couldn\'t resolve alert"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Couldn\'t refresh settings"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Couldn\'t check setting}other{Couldn\'t check settings}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Work profile is paused"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"No info yet"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-en-rXC/strings.xml b/SafetyCenter/Resources/shared_res/values-en-rXC/strings.xml
index 111622cf3..811e6e7fd 100644
--- a/SafetyCenter/Resources/shared_res/values-en-rXC/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-en-rXC/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‎Scanning‎‏‎‎‏‎"</string>
<string name="loading_summary" msgid="3740846439782713910">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎Checking device settings…‎‏‎‎‏‎"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‏‎Looks good‎‏‎‎‏‎"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎No problems found‎‏‎‎‏‎"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎Tip available‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎Tips available‎‏‎‎‏‎}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎No issues found‎‏‎‎‏‎"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎See recommendation‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎See recommendations‎‏‎‎‏‎}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎Action taken‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎Actions taken‎‏‎‎‏‎}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎Review settings‎‏‎‎‏‎"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎Check settings list‎‏‎‎‏‎"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎Potential risks found‎‏‎‎‏‎"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‎Risks found‎‏‎‎‏‎"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎Account may be at risk‎‏‎‎‏‎"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎Account is at risk‎‏‎‎‏‎"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎See alert below‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‎‎‎‏‎‎See alerts below‎‏‎‎‏‎}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎Account at risk‎‏‎‎‏‎"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎See alert‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎See alerts‎‏‎‎‏‎}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎Couldnt open page‎‏‎‎‏‎"</string>
<string name="resolving_action_error" msgid="371968886143262375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‏‎Couldnt resolve alert‎‏‎‎‏‎"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎Couldnt refresh settings‎‏‎‎‏‎"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎Couldnt check setting‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎Couldnt check settings‎‏‎‎‏‎}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‎Work profile is paused‎‏‎‎‏‎"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎No info yet‎‏‎‎‏‎"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-es-rUS/strings.xml b/SafetyCenter/Resources/shared_res/values-es-rUS/strings.xml
index ef0ef2532..29613fc69 100644
--- a/SafetyCenter/Resources/shared_res/values-es-rUS/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-es-rUS/strings.xml
@@ -20,10 +20,10 @@
<string name="scanning_title" msgid="5424849039854311398">"Explorando"</string>
<string name="loading_summary" msgid="3740846439782713910">"Verificando la configuración del dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Todo en orden"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No se encontraron problemas"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Sugerencia disponible}many{Sugerencias disponibles}other{Sugerencias disponibles}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No se encontraron problemas"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Ver recomendación}many{Ver recomendaciones}other{Ver recomendaciones}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Se tomó una medida}many{Se tomaron medidas}other{Se tomaron medidas}}"</string>
- <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisar la configuración"</string>
+ <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisa la configuración"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Verifica la lista de configuración"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"El dispositivo podría estar en riesgo"</string>
<string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"El dispositivo está en riesgo"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Se detectaron riesgos potenciales"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Se detectaron riesgos"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"La cuenta podría estar en riesgo"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"La cuenta está en riesgo"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ve la alerta a continuación}many{Ve las alertas a continuación}other{Ve las alertas a continuación}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"La cuenta está en riesgo"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Ver alerta}many{Ver alertas}other{Ver alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"No se pudo abrir la página"</string>
<string name="resolving_action_error" msgid="371968886143262375">"No se pudo resolver la alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"No se pudo actualizar la configuración"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{No se pudo revisar el parámetro de configuración}many{No se pudieron revisar los parámetros de configuración}other{No se pudieron revisar los parámetros de configuración}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"El perfil de trabajo está en pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Aún no hay información"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-es/strings.xml b/SafetyCenter/Resources/shared_res/values-es/strings.xml
index df61a3507..a13a68d8f 100644
--- a/SafetyCenter/Resources/shared_res/values-es/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-es/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Analizan­do"</string>
<string name="loading_summary" msgid="3740846439782713910">"Comprobando los ajustes del dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Todo correcto"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"No se ha encontrado ningún problema"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Consejo disponible}many{Consejos disponibles}other{Consejos disponibles}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"No se ha detectado ningún problema"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Ver recomendación}many{Ver recomendaciones}other{Ver recomendaciones}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Medida tomada}many{Medidas tomadas}other{Medidas tomadas}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisa los ajustes"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Comprueba la lista de ajustes"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Posibles riesgos detectados"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Riesgos detectados"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"La cuenta puede estar en riesgo"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"La cuenta está en riesgo"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Consulta la alerta a continuación}many{Consulta las alertas a continuación}other{Consulta las alertas a continuación}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"La cuenta está en riesgo"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Ver alerta}many{Ver alertas}other{Ver alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"No se ha podido abrir la página"</string>
<string name="resolving_action_error" msgid="371968886143262375">"No se ha podido resolver la alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"No se han podido actualizar los ajustes"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{No se ha podido comprobar el ajuste}many{No se han podido comprobar los ajustes}other{No se han podido comprobar los ajustes}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"El perfil de trabajo está en pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Aún no hay información"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-et/strings.xml b/SafetyCenter/Resources/shared_res/values-et/strings.xml
index c3662a022..cfe0541d2 100644
--- a/SafetyCenter/Resources/shared_res/values-et/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-et/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skannimine"</string>
<string name="loading_summary" msgid="3740846439782713910">"Seadme seadete kontrollimine …"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Korras"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Probleeme ei leitud"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Saadaval on nõuanne}other{Saadaval on nõuanded}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ühtegi probleemi ei leitud"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Vaadake soovitust}other{Vaadake soovitusi}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Tehti toiming}other{Tehti toimingud}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Vaadake seaded üle"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kontrollige seadete loendit"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Leiti võimalikud ohud"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Leiti ohud"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Konto võib olla ohus"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Konto on ohus"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Vaadake allolevat hoiatust}other{Vaadake allolevaid hoiatusi}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Konto on ohus"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Vaadake hoiatust}other{Vaadake hoiatusi}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Lehte ei saanud avada"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Hoiatusega seotud probleemi ei saanud lahendada"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Seadeid ei saanud värskendada"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Seadet ei õnnestunud kontrollida}other{Seadeid ei õnnestunud kontrollida}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Tööprofiil on peatatud"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Teavet ei ole veel"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-eu/strings.xml b/SafetyCenter/Resources/shared_res/values-eu/strings.xml
index 6ceb84df7..c00cb5827 100644
--- a/SafetyCenter/Resources/shared_res/values-eu/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-eu/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Aztertzen"</string>
<string name="loading_summary" msgid="3740846439782713910">"Gailuaren ezarpenak egiaztatzen…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Ondo dago"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Ez da aurkitu arazorik"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Aholku bat duzu}other{Aholkuak dituzu}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ez da aurkitu arazorik"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Ikusi gomendioa}other{Ikusi gomendioak}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Zerbait egin da}other{Zerbait egin da}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Berrikusi ezarpenak"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Egiaztatu ezarpenen zerrenda"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Balizko arriskuak aurkitu dira"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Arriskuak aurkitu dira"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Baliteke kontua arriskuan egotea"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Kontua arriskuan dago"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ikusi alerta behean}other{Ikusi alertak behean}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Kontua arriskuan dago"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Ikusi alerta}other{Ikusi alertak}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Ezin da ireki orria"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Ezin izan da ebatzi alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Ezin izan dira freskatu ezarpenak"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Ezin izan da egiaztatu ezarpena}other{Ezin izan dira egiaztatu ezarpenak}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Laneko profila pausatuta dago"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ez dago informaziorik oraindik"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-fa/strings.xml b/SafetyCenter/Resources/shared_res/values-fa/strings.xml
index 61f47275d..744ac950c 100644
--- a/SafetyCenter/Resources/shared_res/values-fa/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-fa/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"درحال اسکن کردن"</string>
<string name="loading_summary" msgid="3740846439782713910">"درحال بررسی تنظیمات دستگاه…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"خوب است"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"مشکلی پیدا نشد"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{نکته دردسترس است}one{نکته دردسترس است}other{نکته‌هایی دردسترس است}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"مشکلی پیدا نشد"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{دیدن توصیه}one{دیدن توصیه}other{دیدن توصیه‌ها}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{اقدام انجام شد}one{اقدام انجام شد}other{اقدامات انجام شد}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"مرور تنظیمات"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"بررسی فهرست تنظیمات"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"خطرات احتمالی پیدا شده است"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"خطراتی پیدا شده است"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ممکن است حساب درمعرض خطر باشد"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"حساب درمعرض خطر است"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{دیدن هشدار در زیر}one{دیدن هشدار در زیر}other{دیدن هشدارها در زیر}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"حساب درمعرض خطر است"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{دیدن هشدار}one{دیدن هشدار}other{دیدن هشدارها}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"صفحه باز نشد"</string>
<string name="resolving_action_error" msgid="371968886143262375">"هشدار رفع نشد"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"تنظیمات بازآوری نشد"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{تنظیم بررسی نشد}one{تنظیم بررسی نشد}other{تنظیمات بررسی نشدند}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"نمایه کاری موقتاً متوقف شده است"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"هنوز اطلاعاتی دردسترس نیست"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-fi/strings.xml b/SafetyCenter/Resources/shared_res/values-fi/strings.xml
index 667b9bef2..801b40081 100644
--- a/SafetyCenter/Resources/shared_res/values-fi/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-fi/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skannataan"</string>
<string name="loading_summary" msgid="3740846439782713910">"Tarkistetaan laiteasetuksia…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Hyvältä näyttää"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Ongelmia ei löytynyt"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Vinkki saatavilla}other{Vinkkejä saatavilla}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ongelmia ei havaittu"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Näytä suositus}other{Näytä suositukset}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Tehty toiminto}other{Tehdyt toiminnot}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Tarkista asetukset"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Tarkista asetuslista"</string>
@@ -36,15 +36,14 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Mahdollisia riskejä löydetty"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Tietoturvariskejä löydetty"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Tili voi olla vaarantunut"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Tili on vaarantunut"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Katso ilmoitus alla}other{Katso ilmoitukset alla}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Tili on vaarantunut"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Näytä ilmoitus}other{Näytä ilmoitukset}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Sivun avaaminen epäonnistui"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Hälytyksen ratkaiseminen epäonnistui"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Asetuksia ei voitu päivittää"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Asetuksen tarkistaminen ei onnistunut}other{Asetusten tarkistaminen ei onnistunut}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Työprofiilin käyttö on keskeytetty"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ei vielä tietoa"</string>
- <string name="notification_channel_group_name" msgid="7155072032524876859">"Tietoturva ja yksityisyys"</string>
+ <string name="notification_channel_group_name" msgid="7155072032524876859">"Turvallisuus ja yksityisyys"</string>
<string name="notification_channel_name_information" msgid="2966444432152990166">"Suositukset"</string>
<string name="notification_channel_name_recommendation" msgid="7847408286580217922">"Varoitukset"</string>
<string name="notification_channel_name_critical_warning" msgid="5994320322108351769">"Kriittiset varoitukset"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-fr-rCA/strings.xml b/SafetyCenter/Resources/shared_res/values-fr-rCA/strings.xml
index 4c80652ad..3956c61f5 100644
--- a/SafetyCenter/Resources/shared_res/values-fr-rCA/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-fr-rCA/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Analyse en cours"</string>
<string name="loading_summary" msgid="3740846439782713910">"Vérification des paramètres de l\'appareil en cours…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tout semble correct"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Aucun problème trouvé"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Conseil proposé}one{Conseil proposé}many{Conseils proposés}other{Conseils proposés}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Aucun problème détecté"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Afficher la recommandation}one{Afficher la recommandation}many{Afficher les recommandations}other{Afficher les recommandations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Mesure prise}one{Mesure prise}many{Mesures prises}other{Mesures prises}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Vérifier les paramètres"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Vérifiez la liste des paramètres"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Dangers potentiels trouvés"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Dangers trouvés"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Le compte pourrait être en danger"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Le compte est en danger"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Consultez l\'alerte ci-dessous}one{Consultez l\'alerte ci-dessous}many{Consultez les alertes ci-dessous}other{Consultez les alertes ci-dessous}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Compte à risque"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Afficher l\'alerte}one{Afficher l\'alerte}many{Afficher les alertes}other{Afficher les alertes}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Impossible d\'ouvrir la page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Impossible de résoudre l\'alerte"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Impossible d\'actualiser les paramètres"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Impossible de vérifier le paramètre}one{Impossible de vérifier le paramètre}many{Impossible de vérifier les paramètres}other{Impossible de vérifier les paramètres}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Le profil professionnel est interrompu"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Aucune donnée pour le moment"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-fr/strings.xml b/SafetyCenter/Resources/shared_res/values-fr/strings.xml
index 9a22eaea3..b05f99a15 100644
--- a/SafetyCenter/Resources/shared_res/values-fr/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-fr/strings.xml
@@ -20,13 +20,13 @@
<string name="scanning_title" msgid="5424849039854311398">"Analyse"</string>
<string name="loading_summary" msgid="3740846439782713910">"Vérification des paramètres de l\'appareil…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tout semble bon"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Aucun problème détecté"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Conseil disponible}one{Conseil disponible}many{Conseils disponibles}other{Conseils disponibles}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Aucun problème détecté"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Voir la recommandation}one{Voir la recommandation}many{Voir les recommandations}other{Voir les recommandations}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Mesure prise}one{Mesure prise}many{Mesures prises}other{Mesures prises}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Vérifier les paramètres"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Vérifier la liste des paramètres"</string>
- <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"Risque potentiel sur l\'appareil"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Risque sur l\'appareil"</string>
+ <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"Appareil présentant un risque potentiel"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Appareil présentant un risque"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"Risque potentiel sur vos données"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"Risque sur vos données"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"Mots de passe compromis (anciens)"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"Risque de sécurité"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Risques potentiels détectés"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risques détectés"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Risque potentiel sur le compte"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Risque sur le compte"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Voir l\'alerte ci-dessous}one{Voir l\'alerte ci-dessous}many{Voir les alertes ci-dessous}other{Voir les alertes ci-dessous}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Compte présentant un risque potentiel"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Compte présentant un risque"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Voir l\'alerte}one{Voir l\'alerte}many{Voir les alertes}other{Voir les alertes}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Impossible d\'accéder à la page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Impossible de résoudre l\'alerte"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Impossible d\'actualiser les paramètres"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Impossible de vérifier le paramètre}one{Impossible de vérifier le paramètre}many{Impossible de vérifier les paramètres}other{Impossible de vérifier les paramètres}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profil professionnel en pause"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Aucune info pour l\'instant"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-gl/strings.xml b/SafetyCenter/Resources/shared_res/values-gl/strings.xml
index eaf924353..3a0251dd2 100644
--- a/SafetyCenter/Resources/shared_res/values-gl/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-gl/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Analizando"</string>
<string name="loading_summary" msgid="3740846439782713910">"Comprobando configuración do dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Parece que todo está ben"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Non se atoparon problemas"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Consello dispoñible}other{Consellos dispoñibles}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Non se atopou ningún problema"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Consulta a recomendación}other{Consulta as recomendacións}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Acción levada a cabo}other{Accións levadas a cabo}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisa a configuración"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Revisa a lista de opcións de configuración"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Atopáronse posibles riscos"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Atopáronse riscos"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"A conta pode estar en risco"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"A conta está en risco"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ver a alerta a continuación}other{Ver as alertas a continuación}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"A conta está en risco"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Consulta a alerta}other{Consulta as alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Non se puido abrir a páxina"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Non se puido resolver a alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Non se puido actualizar a configuración"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Non se puido comprobar a opción de configuración}other{Non se puideron comprobar as opcións de configuración}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"O perfil de traballo está en pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Aínda non hai información"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-gu/strings.xml b/SafetyCenter/Resources/shared_res/values-gu/strings.xml
index 6731ec6dd..ded82b3e5 100644
--- a/SafetyCenter/Resources/shared_res/values-gu/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-gu/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"સ્કૅનિંગ"</string>
<string name="loading_summary" msgid="3740846439782713910">"ડિવાઇસના સેટિંગ ચેક કરી રહ્યાં છીએ…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"સરસ દેખાય છે"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"કોઈ સમસ્યા મળી નથી"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ટિપ ઉપલબ્ધ છે}one{ટિપ ઉપલબ્ધ છે}other{ટિપ ઉપલબ્ધ છે}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"કોઈ સમસ્યા મળી નથી"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{સુઝાવ જુઓ}one{સુઝાવ જુઓ}other{સુઝાવો જુઓ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{લેવાયેલું પગલું}one{લેવાયેલું પગલું}other{લેવાયેલા પગલાં}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"સેટિંગનો રિવ્યૂ કરો"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"સેટિંગની સૂચિ ચેક કરો"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"સંભવિત જોખમો મળ્યા"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"જોખમો મળ્યા"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"એકાઉન્ટ જોખમમાં હોઈ શકે છે"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"એકાઉન્ટ જોખમમાં છે"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{નીચે આપેલું અલર્ટ જુઓ}one{નીચે આપેલું અલર્ટ જુઓ}other{નીચે આપેલા અલર્ટ જુઓ}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Google એકાઉન્ટ જોખમમાં"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{અલર્ટ જુઓ}one{અલર્ટ જુઓ}other{અલર્ટ જુઓ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"પેજ ખોલી શક્યા નથી"</string>
<string name="resolving_action_error" msgid="371968886143262375">"અલર્ટનું નિરાકરણ લાવી શક્યા નથી"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"સેટિંગ રિફ્રેશ કરી શકાયા નથી"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{સેટિંગ ચેક કરી શકાયું નથી}one{સેટિંગ ચેક કરી શકાયું નથી}other{સેટિંગ ચેક કરી શકાયા નથી}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ઑફિસની પ્રોફાઇલ થોભાવી છે"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"હજી સુધી કોઈ માહિતી નથી"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-hi/strings.xml b/SafetyCenter/Resources/shared_res/values-hi/strings.xml
index 2df7ef702..6fe62b414 100644
--- a/SafetyCenter/Resources/shared_res/values-hi/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-hi/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"स्कैन किया जा रहा है"</string>
<string name="loading_summary" msgid="3740846439782713910">"डिवाइस सेटिंग की जांच हो रही है…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"डिवाइस सुरक्षित लग रहा है"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"कोई समस्या नहीं मिली"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{सुझाव दिया गया है}one{सुझाव दिया गया है}other{सुझाव दिए गए हैं}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"कोई समस्या नहीं मिली"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{सुझाव देखें}one{सुझाव देखें}other{सुझावों को देखें}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{कार्रवाई की गई है}one{कार्रवाई की गई है}other{कार्रवाइयां की गई हैं}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"सेटिंग देखें"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"सेटिंग की सूची देखें"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"संभावित खतरे का पता चला"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"खतरे का पता चला"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"खाते की सुरक्षा खतरे में हो सकती है"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"खाते की सुरक्षा खतरे में है"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{यहां चेतावनी देखें}one{यहां चेतावनी देखें}other{यहां चेतावनियां देखें}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"खाता की सुरक्षा खतरे में है"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{चेतावनी देखें}one{चेतावनी देखें}other{चेतावनियां देखें}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"पेज को खोला नहीं जा सका"</string>
<string name="resolving_action_error" msgid="371968886143262375">"चेतावनी में बताई गई समस्या को ठीक नहीं किया जा सका"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"सेटिंग को रीफ़्रेश नहीं किया जा सका"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{सेटिंग की जांच नहीं की जा सकी}one{सेटिंग की जांच नहीं की जा सकी}other{सेटिंग की जांच नहीं की जा सकी}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"वर्क प्रोफ़ाइल रोक दी गई है"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"कोई जानकारी मौजूद नहीं है"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-hr/strings.xml b/SafetyCenter/Resources/shared_res/values-hr/strings.xml
index 93f7cba6e..a644d6126 100644
--- a/SafetyCenter/Resources/shared_res/values-hr/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-hr/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Pregled"</string>
<string name="loading_summary" msgid="3740846439782713910">"Provjera postavki uređaja…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Izgleda dobro"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Problemi nisu pronađeni"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Dostupan je savjet}one{Dostupni su savjeti}few{Dostupni su savjeti}other{Dostupni su savjeti}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nije pronađena nijedna poteškoća"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Pogledajte preporuku}one{Pogledajte preporuke}few{Pogledajte preporuke}other{Pogledajte preporuke}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Poduzeta je radnja}one{Poduzete su radnje}few{Poduzete su radnje}other{Poduzete su radnje}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Pregledajte postavke"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Provjera popisa postavki"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Pronađeni su potencijalni rizici"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Pronađeni su rizici"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Račun je možda ugrožen"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Račun je ugrožen"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Pogledajte upozorenje u nastavku}one{Pogledajte upozorenja u nastavku}few{Pogledajte upozorenja u nastavku}other{Pogledajte upozorenja u nastavku}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Račun je ugrožen"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Pogledajte upozorenje}one{Pogledajte upozorenja}few{Pogledajte upozorenja}other{Pogledajte upozorenja}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Otvaranje stranice nije uspjelo"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Razrješavanje upozorenja nije uspjelo"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nije bilo moglo osvježiti postavke"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nije moguće provjeriti postavku}one{Nije moguće provjeriti postavke}few{Nije moguće provjeriti postavke}other{Nije moguće provjeriti postavke}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Poslovni profil je pauziran"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Još nema podataka"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-hu/strings.xml b/SafetyCenter/Resources/shared_res/values-hu/strings.xml
index 48f6d2d60..b8a8540ef 100644
--- a/SafetyCenter/Resources/shared_res/values-hu/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-hu/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Ellenőrzés…"</string>
<string name="loading_summary" msgid="3740846439782713910">"Eszközbeállítások ellenőrzése…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Jónak tűnik"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nem találtunk problémát"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Rendelkezésre áll egy tipp}other{Rendelkezésre állnak tippek}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nem találtunk problémát"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Javaslat megtekintése}other{Javaslatok megtekintése}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Végrehajtott intézkedés}other{Végrehajtott intézkedések}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Beállítások áttekintése"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Ellenőrizze a beállításlistát"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Lehetséges veszélyeket észleltünk"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Veszélyeket észleltünk"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Fiókja veszélyben lehet"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Fiókja veszélyben van"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Tekintse meg az alábbi értesítést}other{Tekintse meg az alábbi értesítéseket}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Veszélyeztetett fiók"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Értesítés megtekintése}other{Értesítések megtekintése}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Nem sikerült megnyitni az oldalt"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Nem sikerült feloldani a figyelmeztetést"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nem sikerült a beállítások frissítése"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nem sikerült a beállítás ellenőrzése}other{Nem sikerült a beállítások ellenőrzése}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"A munkaprofil használata szünetel"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Még nincsenek adatok"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-hy/strings.xml b/SafetyCenter/Resources/shared_res/values-hy/strings.xml
index 8f4344a63..e6b05056b 100644
--- a/SafetyCenter/Resources/shared_res/values-hy/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-hy/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Որոնում"</string>
<string name="loading_summary" msgid="3740846439782713910">"Սարքի կարգավորումները ստուգվում են…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Ամեն ինչ կարգին է"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Որևէ խնդիր չի հայտնաբերվել"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Հասանելի խորհուրդ}one{Հասանելի խորհուրդ}other{Հասանելի խորհուրդներ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Խնդիր չի գտնվել"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Տեսնել առաջարկը}one{Տեսնել առաջարկները}other{Տեսնել առաջարկները}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ձեռնարկված միջոց}one{Ձեռնարկված միջոց}other{Ձեռնարկված միջոցներ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Ստուգեք կարգավորումները"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Ստուգեք կարգավորումների ցանկը"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Հնարավոր ռիսկեր են հայտնաբերվել"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Ռիսկեր են հայտնաբերվել"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Հաշիվը կարող է վտանգված լինել"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Հաշիվը վտանգված է"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ստորև տեսեք զգուշացումը}one{Ստորև տեսեք զգուշացումը}other{Ստորև տեսեք զգուշացումները}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Վտանգված հաշիվ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Տեսնել ծանուցումը}one{Տեսնել ծանուցումները}other{Տեսնել ծանուցումները}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Չհաջողվեց բացել էջը"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Չհաջողվեց լուծել ծանուցումը"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Չհաջողվեց թարմացնել կարգավորումները"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Չհաջողվեց ստուգել կարգավորումը}one{Չհաջողվեց ստուգել կարգավորումը}other{Չհաջողվեց ստուգել կարգավորումները}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Աշխատանքային պրոֆիլը դադարեցված է"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Տեղեկություններ դեռ չկան"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-in/strings.xml b/SafetyCenter/Resources/shared_res/values-in/strings.xml
index 811bedb11..8d25d7340 100644
--- a/SafetyCenter/Resources/shared_res/values-in/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-in/strings.xml
@@ -19,9 +19,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"Memindai"</string>
<string name="loading_summary" msgid="3740846439782713910">"Memeriksa setelan perangkat…"</string>
- <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Semua beres"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Tidak ditemukan masalah"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tips yang tersedia}other{Tips yang tersedia}}"</string>
+ <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Sepertinya semua aman"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Tidak ditemukan masalah"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Lihat rekomendasi}other{Lihat rekomendasi}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Tindakan yang dilakukan}other{Tindakan yang dilakukan}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Tinjau setelan"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Periksa daftar setelan"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potensi risiko ditemukan"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risiko ditemukan"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Akun mungkin berisiko"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Akun berisiko"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Lihat peringatan di bawah ini}other{Lihat peringatan di bawah ini}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Akun berisiko"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Lihat peringatan}other{Lihat peringatan}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Tidak dapat membuka halaman"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Tidak dapat menyelesaikan peringatan"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Tidak dapat merefresh setelan"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Tidak dapat memeriksa setelan}other{Tidak dapat memeriksa setelan}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profil kerja dijeda"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Belum ada info"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-is/strings.xml b/SafetyCenter/Resources/shared_res/values-is/strings.xml
index 4fc822d62..faa4c2e1f 100644
--- a/SafetyCenter/Resources/shared_res/values-is/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-is/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Öryggisleit"</string>
<string name="loading_summary" msgid="3740846439782713910">"Athugar stillingar tækis…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Lítur vel út"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Engin vandamál fundust"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Ábending í boði}one{Ábendingar í boði}other{Ábendingar í boði}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Engin vandamál fundust"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Sjá ráðleggingu}one{Sjá ráðleggingar}other{Sjá ráðleggingar}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Aðgerð sem gripið var til}one{Aðgerðir sem gripið var til}other{Aðgerðir sem gripið var til}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Yfirfara stillingar"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Athuga lista yfir stillingar"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Hugsanleg hætta greindist"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Hætta greindist"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Reikningurinn er hugsanlega í hættu"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Reikningurinn er í hættu"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Sjá viðvörun hér að neðan}one{Sjá viðvaranir hér að neðan}other{Sjá viðvaranir hér að neðan}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Reikningur er í hættu"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Sjá viðvörun}one{Sjá viðvaranir}other{Sjá viðvaranir}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Ekki tókst að opna síðuna"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Ekki tókst að leysa úr viðvöruninni"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Ekki tókst að endurnýja stillingar"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Ekki tókst að athuga stillingu}one{Ekki tókst að athuga stillingar}other{Ekki tókst að athuga stillingar}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Hlé gert á vinnusniði"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Engar upplýsingar ennþá"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-it/strings.xml b/SafetyCenter/Resources/shared_res/values-it/strings.xml
index 049d13632..b2661e84a 100644
--- a/SafetyCenter/Resources/shared_res/values-it/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-it/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Analisi in corso…"</string>
<string name="loading_summary" msgid="3740846439782713910">"Controllo delle impostazioni del dispositivo in corso…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tutto a posto"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nessun problema rilevato"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Suggerimento disponibile}many{Suggerimenti disponibili}other{Suggerimenti disponibili}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nessun problema rilevato"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Visualizza il consiglio}many{Visualizza i consigli}other{Visualizza i consigli}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Azione intrapresa}many{Azioni intraprese}other{Azioni intraprese}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Verifica le impostazioni"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Controlla l\'elenco di impostazioni"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potenziali rischi rilevati"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Rischi rilevati"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"L\'account potrebbe essere a rischio"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"L\'account è a rischio"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Visualizza l\'avviso qui sotto}many{Visualizza gli avvisi qui sotto}other{Visualizza gli avvisi qui sotto}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account a rischio"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Visualizza l\'avviso}many{Visualizza gli avvisi}other{Visualizza gli avvisi}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Impossibile aprire la pagina"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Impossibile risolvere l\'avviso"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Impossibile aggiornare le impostazioni"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Impossibile controllare l\'impostazione}many{Impossibile controllare le impostazioni}other{Impossibile controllare le impostazioni}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profilo di lavoro in pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ancora nessuna informazione"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-iw/strings.xml b/SafetyCenter/Resources/shared_res/values-iw/strings.xml
index 1a3805f1b..8a0794632 100644
--- a/SafetyCenter/Resources/shared_res/values-iw/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-iw/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"מתבצעת סריקה"</string>
<string name="loading_summary" msgid="3740846439782713910">"הגדרות המכשיר נבדקות…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"נראה טוב"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"לא נמצאו בעיות"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{טיפ זמין}one{טיפים זמינים}two{טיפים זמינים}other{טיפים זמינים}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"לא נמצאו בעיות"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{הצגת ההמלצה}one{הצגת ההמלצות}two{הצגת ההמלצות}other{הצגת ההמלצות}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{פעולה בוצעה}one{פעולות בוצעו}two{פעולות בוצעו}other{פעולות בוצעו}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"בדיקת ההגדרות"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"בדיקה של רשימת ההגדרות"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"נמצאו סכנות אפשריות"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"נמצאו סיכונים"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"החשבון עלול להיות בסיכון"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"החשבון בסיכון"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{הצגת ההתראה בהמשך}one{הצגת ההתראות בהמשך}two{הצגת ההתראות בהמשך}other{הצגת ההתראות בהמשך}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"החשבון בסיכון"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{הצגת ההתראה}one{הצגת ההתראות}two{הצגת ההתראות}other{הצגת ההתראות}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"לא ניתן היה לפתוח את הדף"</string>
<string name="resolving_action_error" msgid="371968886143262375">"לא ניתן היה לפתור את הבעיה בהתראה"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"לא ניתן היה לרענן את ההגדרות"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{לא ניתן היה לבדוק את ההגדרה}one{לא ניתן היה לבדוק את ההגדרות}two{לא ניתן היה לבדוק את ההגדרות}other{לא ניתן היה לבדוק את ההגדרות}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"פרופיל העבודה מושהה"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"אין עדיין פרטים"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ja/strings.xml b/SafetyCenter/Resources/shared_res/values-ja/strings.xml
index 9b3a9e708..c6d76eb2c 100644
--- a/SafetyCenter/Resources/shared_res/values-ja/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ja/strings.xml
@@ -20,13 +20,13 @@
<string name="scanning_title" msgid="5424849039854311398">"スキャン"</string>
<string name="loading_summary" msgid="3740846439782713910">"デバイスの設定を確認しています…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"問題はありません"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"問題は見つかりませんでした"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ヒントをご覧いただけます}other{ヒントをご覧いただけます}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"問題は検出されませんでした"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{おすすめを見る}other{おすすめを見る}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{対処しました}other{対処しました}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"設定の確認"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"設定リストをご確認ください"</string>
- <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"デバイスが危険な可能性があります"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"デバイスが危険です"</string>
+ <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"デバイスが危険にさらされています"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"デバイスが危険な状態です"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"データが危険な可能性があります"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"データが危険です"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"古いパスワードの不正使用"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"危険にさらされています"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"潜在的なリスクが検出されました"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"リスクが検出されました"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"アカウントが危険な可能性があります"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"アカウントが危険です"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{下記のアラートをご確認ください}other{下記のアラートをご確認ください}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"アカウントが危険にさらされています"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"アカウントが危険です"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{アラートを確認してください}other{アラートを確認してください}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ページを開けませんでした"</string>
<string name="resolving_action_error" msgid="371968886143262375">"アラートを解決できませんでした"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"設定を更新できませんでした"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{設定を確認できませんでした}other{設定を確認できませんでした}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"仕事用プロファイルが一時停止しています"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"まだ情報がありません"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ka/strings.xml b/SafetyCenter/Resources/shared_res/values-ka/strings.xml
index 7439de354..de8890dec 100644
--- a/SafetyCenter/Resources/shared_res/values-ka/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ka/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"სკანირება"</string>
<string name="loading_summary" msgid="3740846439782713910">"მოწმდება მოწყობილობის პარამეტრები…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ყველაფერი რიგზეა"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"პრობლემები არ მოიძებნა"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{მინიშნება ხელმისაწვდომია}other{მინიშნებები ხელმისაწვდომია}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"პრობლემები ვერ მოიძებნა"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{რეკომენდაციის ნახვა}other{რეკომენდაციების ნახვა}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{მიღებული ქმედება}other{მიღებული ქმედებები}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"პარამეტრების გადახედვა"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"პარამეტრების სიის შემოწმება"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ნაპოვნია პოტენციური რისკები"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"აღმოჩენილი რისკები"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ანგარიშს შესაძლოა საფრთხე ემუქრება"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ანგარიშს საფრთხე ემუქრება"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{იხილეთ გაფრთხილება ქვემოთ}other{იხილეთ გაფრთხილებები ქვემოთ}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"საფრთხის ქვეშ მყოფი ანგარიში"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{გაფრთხილების ნახვა}other{გაფრთხილებების ნახვა}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"გვერდის გახსნა ვერ მოხერხდა"</string>
<string name="resolving_action_error" msgid="371968886143262375">"გაფრთხილება ვერ გადაიჭრა"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"პარამეტრები ვერ განახლდა"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{პარამეტრის შემოწმება ვერ მოხერხდა}other{პარამეტრების Შემოწმება ვერ მოხერხდა}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"სამსახურის პროფილი დაპაუზებულია"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ინფო ჯერ არ არის"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-kk/strings.xml b/SafetyCenter/Resources/shared_res/values-kk/strings.xml
index c3420713b..9226d4fcb 100644
--- a/SafetyCenter/Resources/shared_res/values-kk/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-kk/strings.xml
@@ -20,11 +20,11 @@
<string name="scanning_title" msgid="5424849039854311398">"Тексеріліп жатыр"</string>
<string name="loading_summary" msgid="3740846439782713910">"Құрылғы параметрлері тексеріліп жатыр…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Бәрі дұрыс"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Ешқандай мәселе табылмады."</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Кеңес бар.}other{Кеңестер бар.}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ешқандай мәселе табылмады."</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Ұсынысты көру}other{Ұсыныстарды көру}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Әрекет жасалды.}other{Әрекеттер жасалды.}}"</string>
- <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Параметрлерді қарап шығу"</string>
- <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Параметрлер тізімін тексеру"</string>
+ <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Параметрлерді тексерy"</string>
+ <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Параметрлер тізімін тексеріңіз."</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"Құрылғыға қауіп төнген болуы мүмкін"</string>
<string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Құрылғыға қауіп төніп тұр"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"Деректерге қауіп төнген сияқты"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Қауіп төну мүмкіндігі бар"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Қауіп төніп тұрғаны белгілі болды"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Аккаунтқа қауіп төнген сияқты"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Аккаунтқа қауіп төніп тұр"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Төмендегі хабарландыруды көріңіз.}other{Төмендегі хабарландыруларды көріңіз.}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Аккаунтқа қауіп төніп тұр"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Хабарландыруды көру}other{Хабарландыруларды көру}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Бет ашылмады."</string>
<string name="resolving_action_error" msgid="371968886143262375">"Хабарландыруда көрсетілген мәселе шешілмеді."</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Параметрлер жаңартылмады."</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Параметрді тексеру мүмкін болмады.}other{Параметрлерді тексеру мүмкін болмады.}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Жұмыс профилі кідіртілді."</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Әзірге мәлімет жоқ."</string>
diff --git a/SafetyCenter/Resources/shared_res/values-km/strings.xml b/SafetyCenter/Resources/shared_res/values-km/strings.xml
index 6f0deb271..e1af9019d 100644
--- a/SafetyCenter/Resources/shared_res/values-km/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-km/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"កំពុងស្កេន"</string>
<string name="loading_summary" msgid="3740846439782713910">"កំពុងពិនិត្យមើលការកំណត់ឧបករណ៍…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"គ្មានបញ្ហា​អ្វីទេ"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"រក​មិន​ឃើញ​បញ្ហា​ទេ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{មានគន្លឹះ}other{មានគន្លឹះ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"រកមិន​ឃើញ​បញ្ហាទេ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{មើលការណែនាំ}other{មើល​ការណែនាំ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{សកម្មភាពដែលបានធ្វើឡើង}other{សកម្មភាពដែលបានធ្វើឡើង}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ពិនិត្យមើល​ការកំណត់"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ពិនិត្យបញ្ជីការកំណត់"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"រកឃើញហានិភ័យដែលអាចមាន"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"រកឃើញហានិភ័យ"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"គណនីអាចប្រឈមនឹងហានិភ័យ"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"គណនីប្រឈមនឹងហានិភ័យ"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{មើលការជូន​ដំណឹងខាងក្រោម}other{មើលការជូន​ដំណឹងខាងក្រោម}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"គណនីប្រឈមនឹងហានិភ័យ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{មើលការជូន​ដំណឹង}other{មើលការជូនដំណឹង}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"មិនអាច​បើកទំព័រ​បានទេ"</string>
<string name="resolving_action_error" msgid="371968886143262375">"មិនអាច​ដោះស្រាយការជូនដំណឹងនេះ​បានទេ"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"មិនអាចផ្ទុកការកំណត់ឡើងវិញបានទេ"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{មិន​អាច​ពិនិត្យ​មើល​ការកំណត់​បាន​ទេ}other{មិន​អាច​ពិនិត្យ​មើល​ការកំណត់​បាន​ទេ}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"កម្រងព័ត៌មានការងារត្រូវបាន​ផ្អាក"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"មិន​ទាន់​មាន​ព័ត៌មាន​នៅ​ឡើយ​ទេ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-kn/strings.xml b/SafetyCenter/Resources/shared_res/values-kn/strings.xml
index 6c6272759..46eedaac5 100644
--- a/SafetyCenter/Resources/shared_res/values-kn/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-kn/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
<string name="loading_summary" msgid="3740846439782713910">"ಸಾಧನ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ಸರಿಯಾಗಿದೆ"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ಯಾವುದೇ ಸಮಸ್ಯೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ಸಲಹೆ ಲಭ್ಯವಿದೆ}one{ಸಲಹೆಗಳು ಲಭ್ಯವಿವೆ}other{ಸಲಹೆಗಳು ಲಭ್ಯವಿವೆ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ಯಾವುದೇ ಸಮಸ್ಯೆಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ಶಿಫಾರಸನ್ನು ನೋಡಿ}one{ಶಿಫಾರಸುಗಳನ್ನು ನೋಡಿ}other{ಶಿಫಾರಸುಗಳನ್ನು ನೋಡಿ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ಕ್ರಮ ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ}one{ಕ್ರಮಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ}other{ಕ್ರಮಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಲಾಗಿದೆ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಪಟ್ಟಿಯನ್ನು ಪರಿಶೀಲಿಸಿ"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"ನೀವು ಅಪಾಯದಲ್ಲಿದ್ದೀರಿ"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ಸಂಭವನೀಯ ಅಪಾಯಗಳು ಕಂಡುಬಂದಿವೆ"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ಅಪಾಯಗಳು ಕಂಡುಬಂದಿವೆ"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ಖಾತೆಯು ಅಪಾಯಕ್ಕೀಡಾಗಬಹುದು"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ಖಾತೆ ಅಪಾಯದಲ್ಲಿದೆ"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ಕೆಳಗಿನ ಎಚ್ಚರಿಕೆಯನ್ನು ನೋಡಿ}one{ಕೆಳಗಿನ ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}other{ಕೆಳಗಿನ ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ಖಾತೆಯು ಅಪಾಯದಲ್ಲಿರಬಹುದು"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ಖಾತೆಯು ಅಪಾಯದಲ್ಲಿದೆ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ಎಚ್ಚರಿಕೆಯನ್ನು ನೋಡಿ}one{ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}other{ಎಚ್ಚರಿಕೆಗಳನ್ನು ನೋಡಿ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ಪುಟವನ್ನು ತೆರೆಯಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ಅಲರ್ಟ್ ಅನ್ನು ಬಗೆಹರಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ}one{ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ}other{ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪರಿಶೀಲಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್‌ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ಇನ್ನೂ ಯಾವುದೇ ಮಾಹಿತಿ ಲಭ್ಯವಿಲ್ಲ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ko/strings.xml b/SafetyCenter/Resources/shared_res/values-ko/strings.xml
index e92299496..1a5938c9a 100644
--- a/SafetyCenter/Resources/shared_res/values-ko/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ko/strings.xml
@@ -20,13 +20,13 @@
<string name="scanning_title" msgid="5424849039854311398">"검사 중"</string>
<string name="loading_summary" msgid="3740846439782713910">"기기 설정을 확인하는 중…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"양호"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"문제가 발견되지 않음"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{사용 가능한 팁}other{사용 가능한 팁}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"발견된 문제 없음"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{권장사항 보기}other{권장사항 보기}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{조치를 취함}other{조치를 취함}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"설정 검토"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"설정 목록 확인"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"기기에 잠재적 위험 발생"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"기기 위험 발생"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"기기에 위험 발생"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"데이터에 보안 위험이 있을 수 있음"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"데이터에 보안 위험이 있음"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"기존 비밀번호 손상됨"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"위험에 노출됨"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"잠재적 위험 발견됨"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"위험 발견됨"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"계정에 보안 위험이 있을 수 있음"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"계정에 보안 위험이 있음"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{아래 알림 참고}other{아래 알림 참고}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"계정이 잠재적 위험에 노출됨"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"계정이 위험에 노출됨"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{알림 보기}other{알림 보기}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"페이지를 열 수 없습니다."</string>
<string name="resolving_action_error" msgid="371968886143262375">"알림을 해결할 수 없습니다."</string>
- <string name="refresh_timeout" msgid="251734999692581852">"설정을 새로고침할 수 없습니다."</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{설정을 확인할 수 없습니다.}other{설정을 확인할 수 없습니다.}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"직장 프로필이 일시중지됨"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"아직 정보 없음"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ky/strings.xml b/SafetyCenter/Resources/shared_res/values-ky/strings.xml
index 6f39c7b06..474377b87 100644
--- a/SafetyCenter/Resources/shared_res/values-ky/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ky/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Текшерилүүдө"</string>
<string name="loading_summary" msgid="3740846439782713910">"Түзмөктүн параметрлери текшерилүүдө…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Жакшы эле окшойт"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Баары жайында!"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Кеңеш бар}other{Кеңештер бар}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Маселелер жок"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Сунушту көрүү}other{Сунуштарды көрүү}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Аткарылган аракет}other{Аткарылган аракеттер}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Параметрлерди карап чыгуу"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Параметрлердин тизмесин текшерүү"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Мүмкүн болгон коркунучтар табылды"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Коркунучтар табылды"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Аккаунт коркунучта болушу мүмкүн"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Аккаунттун коопсуздугу коркунучта"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Төмөнкү эскертүүнү көрүү}other{Төмөнкү эскертүүлөрдү көрүү}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Аккаунт коркунучта"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Эскетүүнү көрүү}other{Эскертүүлөрдү көрүү}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Барак ачылган жок"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Эскертүү чечилген жок"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Параметрлер жаңыртылган жок"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Параметр текшерилген жок}other{Параметрлер текшерилген жок}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Жумуш профили тындырылды"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Азырынча маалымат жок"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-lo/strings.xml b/SafetyCenter/Resources/shared_res/values-lo/strings.xml
index 3da550e9a..0abf76b30 100644
--- a/SafetyCenter/Resources/shared_res/values-lo/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-lo/strings.xml
@@ -19,9 +19,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"ການສະແກນ"</string>
<string name="loading_summary" msgid="3740846439782713910">"ກໍາລັງກວດການຕັ້ງຄ່າອຸປະກອນ…"</string>
- <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ເບິ່ງໃຊ້ໄດ້"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ບໍ່ພົບບັນຫາໃດໆ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ເຄັດລັບທີ່ພ້ອມໃຫ້ນຳໃຊ້}other{ເຄັດລັບທີ່ພ້ອມໃຫ້ນຳໃຊ້}}"</string>
+ <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ດີແລ້ວ"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ບໍ່ພົບບັນຫາ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ເບິ່ງຄຳແນະນຳ}other{ເບິ່ງຄຳແນະນຳ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ດຳເນີນການແລ້ວ}other{ດຳເນີນການແລ້ວ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ກວດເບິ່ງການຕັ້ງຄ່າ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ກວດລາຍການການຕັ້ງຄ່າ"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ພົບຄວາມສ່ຽງທີ່ອາດເກີດຂຶ້ນ"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ພົບຄວາມສ່ຽງ"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ບັນຊີອາດຕົກຢູ່ໃນຄວາມສ່ຽງ"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ບັນຊີຕົກຢູ່ໃນຄວາມສ່ຽງ"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ເບິ່ງການແຈ້ງເຕືອນລຸ່ມນີ້}other{ເບິ່ງການແຈ້ງເຕືອນລຸ່ມນີ້}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ບັນຊີຕົກຢູ່ໃນຄວາມສ່ຽງ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ເບິ່ງແຈ້ງເຕືອນ}other{ເບິ່ງແຈ້ງເຕືອນ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ບໍ່ສາມາດເປີດໜ້າໄດ້"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ບໍ່ສາມາດແກ້ໄຂແຈ້ງເຕືອນໄດ້"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ບໍ່ສາມາດໂຫຼດການຕັ້ງຄ່າຄືນໃໝ່"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ກວດສອບການຕັ້ງຄ່າບໍ່ໄດ້}other{ກວດສອບການຕັ້ງຄ່າບໍ່ໄດ້}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ຢຸດໂປຣໄຟລ໌ວຽກໄວ້ຊົ່ວຄາວແລ້ວ"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ບໍ່ມີຂໍ້ມູນເທື່ອ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-lt/strings.xml b/SafetyCenter/Resources/shared_res/values-lt/strings.xml
index bdfe7600d..832ef32f1 100644
--- a/SafetyCenter/Resources/shared_res/values-lt/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-lt/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Nuskaitoma"</string>
<string name="loading_summary" msgid="3740846439782713910">"Tikrinami įrenginio nustatymai…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Viskas gerai"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nerasta jokių problemų"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Yra patarimas}one{Yra patarimų}few{Yra patarimų}many{Yra patarimų}other{Yra patarimų}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Problemų neaptikta"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Žr. rekomendaciją}one{Žr. rekomendacijas}few{Žr. rekomendacijas}many{Žr. rekomendacijas}other{Žr. rekomendacijas}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Veiksmas atliktas}one{Veiksmai atlikti}few{Veiksmai atlikti}many{Veiksmai atlikti}other{Veiksmai atlikti}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Žr. nustatymus"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Tikrinti nustatymų sąrašą"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Aptikta potencialių pavojų"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Aptikta pavojų"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Paskyrai galėjo kilti pavojus"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Paskyrai kilo pavojus"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Žr. toliau pateiktą įspėjimą}one{Žr. toliau pateiktus įspėjimus}few{Žr. toliau pateiktus įspėjimus}many{Žr. toliau pateiktus įspėjimus}other{Žr. toliau pateiktus įspėjimus}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Paskyrai iškilo pavojus"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Žr. įspėjimą}one{Žr. įspėjimus}few{Žr. įspėjimus}many{Žr. įspėjimus}other{Žr. įspėjimus}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Nepavyko atidaryti puslapio"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Nepavyko pašalinti įspėjimo"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nepavyko atnaujinti nustatymų"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nepavyko patikrinti nustatymo}one{Nepavyko patikrinti nustatymų}few{Nepavyko patikrinti nustatymų}many{Nepavyko patikrinti nustatymų}other{Nepavyko patikrinti nustatymų}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Darbo profilis pristabdytas"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Kol kas informacijos nėra"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-lv/strings.xml b/SafetyCenter/Resources/shared_res/values-lv/strings.xml
index 3563a1b22..eb544b15f 100644
--- a/SafetyCenter/Resources/shared_res/values-lv/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-lv/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Notiek pārbaude"</string>
<string name="loading_summary" msgid="3740846439782713910">"Notiek ierīces iestatījumu pārbaude…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Viss kārtībā"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Netika atrasta neviena problēma"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Pieejams padoms}zero{Pieejami padomi}one{Pieejami padomi}other{Pieejami padomi}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Problēmas netika atrastas"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Skatiet ieteikumu}zero{Skatiet ieteikumus}one{Skatiet ieteikumus}other{Skatiet ieteikumus}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Veikta darbība}zero{Veiktas darbības}one{Veiktas darbības}other{Veiktas darbības}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Pārskatiet iestatījumus"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Pārbaudiet iestatījumu sarakstu"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Konstatēts iespējams risks"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Konstatēts risks"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Konts var būt apdraudēts"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Konts ir apdraudēts"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Skatiet tālāk norādīto brīdinājumu}zero{Skatiet tālāk norādītos brīdinājumus}one{Skatiet tālāk norādītos brīdinājumus}other{Skatiet tālāk norādītos brīdinājumus}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Konts ir apdraudēts"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Skatiet brīdinājumu}zero{Skatiet brīdinājumus}one{Skatiet brīdinājumus}other{Skatiet brīdinājumus}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Nevarēja atvērt lapu"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Nevarēja atrisināt ieteikumu vai brīdinājumu"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nevarēja atsvaidzināt iestatījumus"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nevarēja pārbaudīt iestatījumu.}zero{Nevarēja pārbaudīt iestatījumus.}one{Nevarēja pārbaudīt iestatījumus.}other{Nevarēja pārbaudīt iestatījumus.}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Darba profila darbība ir apturēta"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Vēl nav informācijas"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-mk/strings.xml b/SafetyCenter/Resources/shared_res/values-mk/strings.xml
index 9bced888c..30b405c67 100644
--- a/SafetyCenter/Resources/shared_res/values-mk/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-mk/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Скенирање"</string>
<string name="loading_summary" msgid="3740846439782713910">"Се проверуваат поставките за уредот…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Изгледа добро"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Не се најдени проблеми"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Достапен е совет}one{Достапни се совети}other{Достапни се совети}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Не се најдени проблеми"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Видете ја препораката}one{Видете ги препораките}other{Видете ги препораките}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Преземено дејство}one{Преземени дејства}other{Преземени дејства}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Прегледајте ги поставките"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Проверете го списокот со поставки"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"Под ризик сте"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Најдени се потенцијални ризици"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Најдени се ризици"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Сметката можеби е под ризик"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Сметката е под ризик"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Видете го предупредувањето подолу}one{Видете ги предупредувањата подолу}other{Видете ги предупредувањата подолу}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Сметката можеби е изложена на ризик"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Сметката е изложена на ризик"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Видете го предупредувањето}one{Видете ги предупредувањата}other{Видете ги предупредувањата}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Не можеше да се отвори страницата"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Не можеше да се реши предупредувањето"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Не можеше да се освежат поставките"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Не може да се провери поставката}one{Не може да се проверат поставките}other{Не може да се проверат поставките}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Работниот профил е паузиран"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Сѐ уште нема податоци"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ml/strings.xml b/SafetyCenter/Resources/shared_res/values-ml/strings.xml
index 6e666ec16..4a77469da 100644
--- a/SafetyCenter/Resources/shared_res/values-ml/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ml/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"സ്‌കാൻ ചെയ്യുന്നു"</string>
<string name="loading_summary" msgid="3740846439782713910">"ഉപകരണ ക്രമീകരണം പരിശോധിക്കുന്നു…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"കൊള്ളാം"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"പ്രശ്‌നങ്ങളൊന്നും കണ്ടെത്തിയില്ല"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{നുറുങ്ങ് ലഭ്യമാണ്}other{നുറുങ്ങുകൾ ലഭ്യമാണ്}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"പ്രശ്‌നങ്ങളൊന്നും കണ്ടെത്തിയില്ല"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{നിർദ്ദേശം കാണുക}other{നിർദ്ദേശങ്ങൾ കാണുക}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{എടുത്ത നടപടി}other{എടുത്ത നടപടികൾ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ക്രമീകരണം അവലോകനം ചെയ്യുക"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ക്രമീകരണ ലിസ്റ്റ് പരിശോധിക്കുക"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"സാധ്യതയുള്ള അപകടസാധ്യതകൾ കണ്ടെത്തി"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"അപകടസാധ്യതകൾ കണ്ടെത്തി"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"അക്കൗണ്ട് അപകടത്തിലായേക്കാം"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"അക്കൗണ്ട് അപകടത്തിലാണ്"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{താഴെയുള്ള മുന്നറിയിപ്പ് കാണുക}other{താഴെയുള്ള മുന്നറിയിപ്പുകൾ കാണുക}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"അക്കൗണ്ട് അപകടത്തിലാണ്"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{മുന്നറിയിപ്പ് കാണുക}other{മുന്നറിയിപ്പുകൾ കാണുക}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"പേജ് തുറക്കാനായില്ല"</string>
<string name="resolving_action_error" msgid="371968886143262375">"മുന്നറിയിപ്പ് പരിഹരിക്കാനായില്ല"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ക്രമീകരണം റീഫ്രഷ് ചെയ്യാനായില്ല"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ക്രമീകരണം പരിശോധിക്കാനായില്ല}other{ക്രമീകരണം പരിശോധിക്കാനായില്ല}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ഔദ്യോഗിക പ്രൊഫൈൽ തൽക്കാലം നിർത്തിയിരിക്കുന്നു"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ഇതുവരെ വിവരങ്ങളൊന്നുമില്ല"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-mn/strings.xml b/SafetyCenter/Resources/shared_res/values-mn/strings.xml
index 76be45d32..88f75f648 100644
--- a/SafetyCenter/Resources/shared_res/values-mn/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-mn/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Скан хийж байна"</string>
<string name="loading_summary" msgid="3740846439782713910">"Төхөөрөмжийн тохиргоог шалгаж байна…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Сайн байна"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Асуудал олдсонгүй"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Зөвлөгөө боломжтой}other{Зөвлөгөөнүүд боломжтой}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ямар ч асуудал олдсонгүй"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Зөвлөмжийг харах}other{Зөвлөмжүүдийг харах}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Арга хэмжээ авсан}other{Арга хэмжээнүүд авсан}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Тохиргоог шалгах"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Тохиргооны жагсаалтыг шалгах"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Боломжит эрсдэл илэрсэн"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Эрсдэл илэрсэн"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Бүртгэл эрсдэлд байж магадгүй"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Бүртгэл эрсдэлд байна"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Доорх сэрэмжлүүлгийг харна уу}other{Доорх сэрэмжлүүлгүүдийг харна уу}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Бүртгэл эрсдэлд байна"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Сэрэмжлүүлгийг харах}other{Сэрэмжлүүлгүүдийг харах}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Хуудсыг нээж чадсангүй"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Сэрэмжлүүлгийг шийдвэрлэж чадсангүй"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Тохиргоог сэргээж чадсангүй"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Тохиргоог шалгаж чадсангүй}other{Тохиргоог шалгаж чадсангүй}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Ажлын профайлыг түр зогсоосон"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Мэдээлэл хараахан алга"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-mr/strings.xml b/SafetyCenter/Resources/shared_res/values-mr/strings.xml
index ec145d0f4..0b47053cd 100644
--- a/SafetyCenter/Resources/shared_res/values-mr/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-mr/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"स्कॅन करत आहे"</string>
<string name="loading_summary" msgid="3740846439782713910">"डिव्हाइस सेटिंग्ज तपासत आहे…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"चांगले दिसते आहे"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"कोणत्‍याही समस्‍या आढळल्‍या नाहीत"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{टीप उपलब्ध}other{टीपा उपलब्ध}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"कोणत्याही समस्या आढळल्या नाहीत"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{शिफारस पहा}other{शिफारशी पहा}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{कृती केली}other{कृती केल्या}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"सेटिंग्जचे पुनरावलोकन करा"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"सेटिंग्जची सूची तपासा"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"संभाव्य धोके आढळले"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"धोके आढळले"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"खाते धोक्यात असू शकते"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"खाते धोक्यात आहे"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{सूचना खाली पहा}other{सूचना खाली पहा}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"खाते धोक्यात आहे"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{सूचना पहा}other{सूचना पहा}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"पेज उघडता आले नाही"</string>
<string name="resolving_action_error" msgid="371968886143262375">"इशाऱ्याचे निराकरण करता आले नाही"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"सेटिंग्ज रिफ्रेश करता आली नाही"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{सेटिंग तपासता आले नाही}other{सेटिंग्ज तपासता आली नाहीत}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"कार्य प्रोफाइल थांबवली आहे"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"अद्याप कोणतीही माहिती नाही"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ms/strings.xml b/SafetyCenter/Resources/shared_res/values-ms/strings.xml
index 4af3570d8..f8c3e2c32 100644
--- a/SafetyCenter/Resources/shared_res/values-ms/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ms/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Mengimbas"</string>
<string name="loading_summary" msgid="3740846439782713910">"Menyemak tetapan peranti…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Semuanya baik"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Tiada masalah ditemukan"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Petua tersedia}other{Petua tersedia}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Tiada isu ditemukan"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Lihat syor}other{Lihat syor}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Tindakan diambil}other{Tindakan diambil}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Semak tetapan"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Semak senarai tetapan"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Risiko berpotensi ditemukan"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risiko ditemukan"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Akaun mungkin berisiko"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Akaun berisiko"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Lihat makluman di bawah}other{Lihat makluman di bawah}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Akaun berisiko"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Lihat makluman}other{Lihat makluman}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Tidak dapat membuka halaman"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Tidak dapat menyelesaikan amaran"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Tidak dapat menyegar semula tetapan"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Tidak dapat menyemak tetapan}other{Tidak dapat menyemak tetapan}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profil kerja dijeda"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Belum ada maklumat lagi"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-my/strings.xml b/SafetyCenter/Resources/shared_res/values-my/strings.xml
index 1169ab0c2..76e53c8dc 100644
--- a/SafetyCenter/Resources/shared_res/values-my/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-my/strings.xml
@@ -20,13 +20,13 @@
<string name="scanning_title" msgid="5424849039854311398">"စကင်ဖတ်ခြင်း"</string>
<string name="loading_summary" msgid="3740846439782713910">"စက်၏ဆက်တင်များကို စစ်ဆေးနေသည်…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"အဆင်ပြေပါသည်"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ပြဿနာမတွေ့ပါ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{အကြံပြုချက် ရှိသည်}other{အကြံပြုချက်များ ရှိသည်}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ပြဿနာ မတွေ့ပါ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{အကြံပြုချက် ကြည့်ရန်}other{အကြံပြုချက်များ ကြည့်ရန်}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{လုပ်ဆောင်မှု ရှိသည်}other{လုပ်ဆောင်မှုများ ရှိသည်}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ဆက်တင်များကို စိစစ်ပါ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ဆက်တင်များစာရင်းကို စစ်ဆေးပါ"</string>
- <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"စက်တွင် အန္တရာယ်ရှိနိုင်သည်"</string>
- <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"စက်တွင် အန္တရာယ်ရှိနေသည်"</string>
+ <string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"စက်အတွက် အန္တရာယ်ရှိနိုင်သည်"</string>
+ <string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"စက်အတွက် အန္တရာယ်ရှိနေသည်"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"သင့်ဒေတာတွင် အန္တရာယ်ရှိနိုင်သည်"</string>
<string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"သင့်ဒေတာတွင် အန္တရာယ်ရှိသည်"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"စကားဝှက် ကျိုးပေါက်နေသည် (အဟောင်း)"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"သင့်တွင် အန္တရာယ်ရှိနေသည်"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"အန္တရာယ်ဖြစ်နိုင်ခြေ တွေ့သည်"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"အန္တရာယ် တွေ့ထားသည်"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"အကောင့်တွင် အန္တရာယ်ရှိနိုင်သည်"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"အကောင့်တွင် အန္တရာယ်ရှိသည်"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{အောက်ပါ သတိပေးချက်ကို ကြည့်ပါ}other{အောက်ပါ သတိပေးချက်များကို ကြည့်ပါ}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"အကောင့်အတွက် အန္တရာယ်ရှိနိုင်သည်"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"အကောင့်အတွက် အန္တရာယ်ရှိသည်"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{သတိပေးချက် ကြည့်ရန်}other{သတိပေးချက်များ ကြည့်ရန်}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"စာမျက်နှာကို ဖွင့်၍မရပါ"</string>
<string name="resolving_action_error" msgid="371968886143262375">"သတိပေးချက်ကို ဖြေရှင်း၍မရပါ"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ဆက်တင်များကို ပြန်လည် စတင်၍မရပါ"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ဆက်တင်ကြည့်၍မရပါ}other{ဆက်တင်များ ကြည့်၍မရပါ}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"အလုပ်ပရိုဖိုင် ခဏရပ်ထားသည်"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"အချက်အလက် မရှိသေးပါ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-nb/strings.xml b/SafetyCenter/Resources/shared_res/values-nb/strings.xml
index 02da7c32c..61338a390 100644
--- a/SafetyCenter/Resources/shared_res/values-nb/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-nb/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skanner"</string>
<string name="loading_summary" msgid="3740846439782713910">"Sjekker enhetsinnstillingene …"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Dette ser bra ut"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Fant ingen problemer"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Et tips er tilgjengelig}other{Noen tips er tilgjengelige}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Fant ingen problemer"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Se anbefalingen}other{Se anbefalingene}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Handlingen er iverksatt}other{Handlingene er iverksatt}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Gå gjennom innstillingene"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Sjekk innstillingslisten"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potensielle risikoer er registrert"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risikoer er registrert"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Kontoen kan være i faresonen"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Kontoen er i faresonen"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Se varselet nedenfor}other{Se varslene nedenfor}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Kontoen er i faresonen"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Se varselet}other{Se varslene}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Kunne ikke åpne siden"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Kunne ikke løse varselet"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Kunne ikke laste inn innstillingene på nytt"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Kunne ikke sjekke innstillingen}other{Kunne ikke sjekke innstillingene}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Jobbprofilen er satt på pause"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ingen informasjon ennå"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ne/strings.xml b/SafetyCenter/Resources/shared_res/values-ne/strings.xml
index 7358af100..e7c392a3b 100644
--- a/SafetyCenter/Resources/shared_res/values-ne/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ne/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"स्क्यान गरिँदै छ"</string>
<string name="loading_summary" msgid="3740846439782713910">"डिभाइसका सेटिङ जाँचिदै छ…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"सबै कुरा ठिकै देखिन्छ"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"कुनै पनि समस्या भेटिएन"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{सुझाव उपलब्ध छ}other{सुझावहरू उपलब्ध छन्}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"कुनै पनि समस्या भेटिएन"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{सिफारिस हेर्नुहोस्}other{सिफारिसहरू हेर्नुहोस्}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{कारबाही गरिएको छ}other{कारबाहीहरू गरिएका छन्}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"सेटिङको समीक्षा गर्नुहोस्"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"सेटिङको सूची जाँच्नुहोस्"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"सम्भावित जोखिम फेला परे"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"जोखिम फेला परे"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"खाता जोखिममा हुन सक्छ"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"खाता जोखिममा छ"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{तल दिइएको अलर्ट हेर्नुहोस्}other{तल दिइएका अलर्टहरू हेर्नुहोस्}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"खाता जोखिममा छ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{अलर्ट हेर्नुहोस्}other{अलर्टहरू हेर्नुहोस्}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"पेज खोल्न सकिएन"</string>
<string name="resolving_action_error" msgid="371968886143262375">"अलर्ट समाधान गर्न सकिएन"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"सेटिङ रिफ्रेस गर्न सकिएन"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{सेटिङ जाँच गर्न सकिएन}other{सेटिङहरू जाँच गर्न सकिएन}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"कार्य प्रोफाइल पज गरिएको छ"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"कुनै जानकारी उपलब्ध छैन"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-nl/strings.xml b/SafetyCenter/Resources/shared_res/values-nl/strings.xml
index fbde4bf79..ab8edda5d 100644
--- a/SafetyCenter/Resources/shared_res/values-nl/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-nl/strings.xml
@@ -18,10 +18,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"Scannen"</string>
- <string name="loading_summary" msgid="3740846439782713910">"Apparaat-instellingen&amp;#173checken…"</string>
+ <string name="loading_summary" msgid="3740846439782713910">"Apparaat­instellingen­ checken…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Dat ziet er goed uit"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Geen problemen gevonden"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Beschikbare tip}other{Beschikbare tips}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Geen problemen gevonden"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Aanbeveling bekijken}other{Aanbevelingen bekijken}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ondernomen actie}other{Ondernomen acties}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Instellingen checken"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Check de lijst met instellingen"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potentiële risico\'s gevonden"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risico\'s gevonden"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Account loopt misschien gevaar"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Account loopt risico"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Zie onderstaande melding}other{Zie onderstaande meldingen}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Account loopt gevaar"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Melding bekijken}other{Meldingen bekijken}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Kan de pagina niet openen"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Kan melding niet oplossen"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Kan instellingen niet vernieuwen"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Kan instelling niet checken}other{Kan instellingen niet checken}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Werkprofiel is onderbroken"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Nog geen informatie"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-or/strings.xml b/SafetyCenter/Resources/shared_res/values-or/strings.xml
index 5760e83a3..341149120 100644
--- a/SafetyCenter/Resources/shared_res/values-or/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-or/strings.xml
@@ -19,9 +19,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"ସ୍କାନ କରାଯାଉଛି"</string>
<string name="loading_summary" msgid="3740846439782713910">"ଡିଭାଇସ ସେଟିଂସ ଯାଞ୍ଚ କରାଯାଉଛି…"</string>
- <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ଠିକ୍ ଥିବା ପରି ଜଣାପଡ଼ୁଛି"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"କୌଣସି ସମସ୍ୟା ମିଳିଲା ନାହିଁ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ଉପଲବ୍ଧ ଟିପ}other{ଉପଲବ୍ଧ ଟିପ୍ସ}}"</string>
+ <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ଠିକ ଥିବା ପରି ଲାଗୁଛି"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"କୌଣସି ସମସ୍ୟା ମିଳିଲା ନାହିଁ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ସୁପାରିଶ ଦେଖନ୍ତୁ}other{ସୁପାରିଶଗୁଡ଼ିକ ଦେଖନ୍ତୁ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ନିଆଯାଇଥିବା ପଦକ୍ଷେପ}other{ନିଆଯାଇଥିବା ପଦକ୍ଷେପଗୁଡ଼ିକ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ସେଟିଂସର ସମୀକ୍ଷା କରନ୍ତୁ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ସେଟିଂସ ତାଲିକା ଯାଞ୍ଚ କରନ୍ତୁ"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"ଆପଣ ବିପଦରେ ଅଛନ୍ତି"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ସମ୍ଭାବ୍ୟ ବିପଦ ମିଳିଛି"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ବିପଦ ମିଳିଛି"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ଆକାଉଣ୍ଟ ବିପଦରେ ଥାଇପାରେ"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ଆକାଉଣ୍ଟ ବିପଦରେ ଅଛି"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ନିମ୍ନରେ ଆଲର୍ଟ ଦେଖନ୍ତୁ}other{ନିମ୍ନରେ ଆଲର୍ଟଗୁଡ଼ିକ ଦେଖନ୍ତୁ}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ଆକାଉଣ୍ଟଟି ରିସ୍କରେ ଥାଇପାରେ"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ଆକାଉଣ୍ଟଟି ରିସ୍କରେ ଅଛି"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ଆଲର୍ଟ ଦେଖନ୍ତୁ}other{ଆଲର୍ଟଗୁଡ଼ିକ ଦେଖନ୍ତୁ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ପୃଷ୍ଠାକୁ ଖୋଲା ଯାଇପାରିଲା ନାହିଁ"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ଆଲର୍ଟର ସମାଧାନ କରାଯାଇପାରିଲା ନାହିଁ"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ସେଟିଂସ ରିଫ୍ରେସ କରାଯାଇପାରିଲା ନାହିଁ"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ସେଟିଂ ଯାଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ}other{ସେଟିଂସ ଯାଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ବିରତ କରାଯାଇଛି"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ଏପର୍ଯ୍ୟନ୍ତ କୌଣସି ସୂଚନା ନାହିଁ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-pa/strings.xml b/SafetyCenter/Resources/shared_res/values-pa/strings.xml
index 022353905..54aad5cbb 100644
--- a/SafetyCenter/Resources/shared_res/values-pa/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-pa/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="loading_summary" msgid="3740846439782713910">"ਡੀਵਾਈਸ ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ਸਭ ਕੁਝ ਠੀਕ ਲੱਗ ਰਿਹਾ ਹੈ"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਮਿਲੀ"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ਨੁਕਤਾ ਉਪਲਬਧ ਹੈ}one{ਨੁਕਤਾ ਉਪਲਬਧ ਹੈ}other{ਨੁਕਤੇ ਉਪਲਬਧ ਹਨ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਮਿਲੀ"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ਸਿਫ਼ਾਰਸ਼ ਦੇਖੋ}one{ਸਿਫ਼ਾਰਸ਼ ਦੇਖੋ}other{ਸਿਫ਼ਾਰਸ਼ਾਂ ਦੇਖੋ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ਕੀਤੀ ਗਈ ਕਾਰਵਾਈ}one{ਕੀਤੀ ਗਈ ਕਾਰਵਾਈ}other{ਕੀਤੀਆਂ ਗਈਆਂ ਕਾਰਵਾਈਆਂ}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ਸੈਟਿੰਗਾਂ ਦੀ ਸਮੀਖਿਆ ਕਰੋ"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ਸੈਟਿੰਗਾਂ ਸੂਚੀ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ਸੰਭਾਵੀ ਜੋਖਮਾਂ ਦਾ ਪਤਾ ਲੱਗਿਆ"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ਜੋਖਮਾਂ ਦਾ ਪਤਾ ਲੱਗਿਆ"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ਖਾਤਾ ਜੋਖਮ ਵਿੱਚ ਹੋ ਸਕਦਾ ਹੈ"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ਖਾਤਾ ਜੋਖਮ ਵਿੱਚ ਹੈ"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ਹੇਠਾਂ ਸੁਚੇਤਨਾ ਦੇਖੋ}one{ਹੇਠਾਂ ਸੁਚੇਤਨਾ ਦੇਖੋ}other{ਹੇਠਾਂ ਸੁਚੇਤਨਾਵਾਂ ਦੇਖੋ}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ਖਾਤਾ ਜੋਖਮ ਵਿੱਚ ਹੈ"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ਅਲਰਟ ਦੇਖੋ}one{ਅਲਰਟ ਦੇਖੋ}other{ਅਲਰਟ ਦੇਖੋ}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"ਪੰਨਾ ਖੋਲ੍ਹਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ਸੁਚੇਤਨਾ ਦਾ ਹੱਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ਸੈਟਿੰਗਾਂ ਨੂੰ ਰਿਫ੍ਰੈਸ਼ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ਸੈਟਿੰਗ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕੇ}one{ਸੈਟਿੰਗ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕੇ}other{ਸੈਟਿੰਗਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕੇ}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਰੋਕਿਆ ਗਿਆ ਹੈ"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ਅਜੇ ਕੋਈ ਜਾਣਕਾਰੀ ਨਹੀਂ ਹੈ"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-pl/strings.xml b/SafetyCenter/Resources/shared_res/values-pl/strings.xml
index 23717053e..89a242e7f 100644
--- a/SafetyCenter/Resources/shared_res/values-pl/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-pl/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Skanowanie"</string>
<string name="loading_summary" msgid="3740846439782713910">"Sprawdzam ustawienia urządzenia…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"OK"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nie znaleziono problemów"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Dostępna wskazówka}few{Dostępne wskazówki}many{Dostępne wskazówki}other{Dostępne wskazówki}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nie znaleziono problemów"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Zobacz rekomendację}few{Zobacz rekomendacje}many{Zobacz rekomendacje}other{Zobacz rekomendacje}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Podjęliśmy działanie}few{Podjęliśmy działania}many{Podjęliśmy działania}other{Podjęliśmy działania}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Sprawdź ustawienia"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Sprawdź listę ustawień"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Wykryte potencjalne zagrożenia"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Wykryte zagrożenia"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Konto może być zagrożone"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Konto jest zagrożone"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Zobacz alert poniżej}few{Zobacz alerty poniżej}many{Zobacz alerty poniżej}other{Zobacz alerty poniżej}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Konto jest zagrożone"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Zobacz alert}few{Zobacz alerty}many{Zobacz alerty}other{Zobacz alerty}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Nie udało się otworzyć strony"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Nie udało się rozwiązać problemu z alertu"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nie udało się odświeżyć ustawień"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nie udało się sprawdzić ustawienia}few{Nie udało się sprawdzić ustawień}many{Nie udało się sprawdzić ustawień}other{Nie udało się sprawdzić ustawień}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Wstrzymano profil służbowy"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Nie ma jeszcze informacji"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-pt-rBR/strings.xml b/SafetyCenter/Resources/shared_res/values-pt-rBR/strings.xml
index c2a8b53ad..0599f1c24 100644
--- a/SafetyCenter/Resources/shared_res/values-pt-rBR/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-pt-rBR/strings.xml
@@ -17,11 +17,11 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="scanning_title" msgid="5424849039854311398">"Verifican­‐do"</string>
+ <string name="scanning_title" msgid="5424849039854311398">"Verifican­do"</string>
<string name="loading_summary" msgid="3740846439782713910">"Verificando configurações do dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tudo certo"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nenhum problema encontrado"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Dica disponível}one{Dica disponível}many{Dicas disponíveis}other{Dicas disponíveis}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nenhum problema foi encontrado"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Mostrar recomendação}one{Mostrar recomendação}many{Mostrar recomendações}other{Mostrar recomendações}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ação realizada}one{Ação realizada}many{Ações realizadas}other{Ações realizadas}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisar configurações"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Verificar lista de configurações"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Possíveis riscos encontrados"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Riscos encontrados"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"A conta pode estar em risco"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"A conta está em risco"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Conferir alerta abaixo}one{Conferir alerta abaixo}many{Conferir alertas abaixo}other{Conferir alertas abaixo}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Conta em risco"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Mostrar alerta}one{Mostrar alerta}many{Mostrar alertas}other{Mostrar alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Não foi possível abrir a página"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Não foi possível resolver o alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Não foi possível atualizar as configurações"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Não foi possível verificar a configuração}one{Não foi possível verificar a configuração}many{Não foi possível verificar as configurações}other{Não foi possível verificar as configurações}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"O perfil de trabalho está pausado"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ainda não há informações"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-pt-rPT/strings.xml b/SafetyCenter/Resources/shared_res/values-pt-rPT/strings.xml
index e7ccb1281..835b8a14f 100644
--- a/SafetyCenter/Resources/shared_res/values-pt-rPT/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-pt-rPT/strings.xml
@@ -20,10 +20,10 @@
<string name="scanning_title" msgid="5424849039854311398">"A analisar"</string>
<string name="loading_summary" msgid="3740846439782713910">"A verificar as definições do dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Parece estar tudo bem"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nenhum problema encontrado"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Sugestão disponível}many{Sugestões disponíveis}other{Sugestões disponíveis}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nenhum problema encontrado"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Veja a recomendação}many{Veja as recomendações}other{Veja as recomendações}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Medida tomada}many{Medidas tomadas}other{Medidas tomadas}}"</string>
- <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Reveja as definições"</string>
+ <string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Rever definições"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Verifique a lista de definições"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"O dispositivo pode estar em risco"</string>
<string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"O dispositivo está em risco"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potenciais riscos encontrados"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Riscos encontrados"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"A conta pode estar em risco"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"A conta está em risco"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Veja o alerta abaixo}many{Veja os alertas abaixo}other{Veja os alertas abaixo}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Conta em risco"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Veja o alerta}many{Veja os alertas}other{Veja os alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Não foi possível abrir a página"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Não foi possível resolver o alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Não foi possível atualizar as definições"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Não foi possível verificar a definição}many{Não foi possível verificar as definições}other{Não foi possível verificar as definições}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Perfil de trabalho em pausa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ainda sem informações"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-pt/strings.xml b/SafetyCenter/Resources/shared_res/values-pt/strings.xml
index c2a8b53ad..0599f1c24 100644
--- a/SafetyCenter/Resources/shared_res/values-pt/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-pt/strings.xml
@@ -17,11 +17,11 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="scanning_title" msgid="5424849039854311398">"Verifican­‐do"</string>
+ <string name="scanning_title" msgid="5424849039854311398">"Verifican­do"</string>
<string name="loading_summary" msgid="3740846439782713910">"Verificando configurações do dispositivo…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Tudo certo"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nenhum problema encontrado"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Dica disponível}one{Dica disponível}many{Dicas disponíveis}other{Dicas disponíveis}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nenhum problema foi encontrado"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Mostrar recomendação}one{Mostrar recomendação}many{Mostrar recomendações}other{Mostrar recomendações}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ação realizada}one{Ação realizada}many{Ações realizadas}other{Ações realizadas}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Revisar configurações"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Verificar lista de configurações"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Possíveis riscos encontrados"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Riscos encontrados"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"A conta pode estar em risco"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"A conta está em risco"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Conferir alerta abaixo}one{Conferir alerta abaixo}many{Conferir alertas abaixo}other{Conferir alertas abaixo}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Conta em risco"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Mostrar alerta}one{Mostrar alerta}many{Mostrar alertas}other{Mostrar alertas}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Não foi possível abrir a página"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Não foi possível resolver o alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Não foi possível atualizar as configurações"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Não foi possível verificar a configuração}one{Não foi possível verificar a configuração}many{Não foi possível verificar as configurações}other{Não foi possível verificar as configurações}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"O perfil de trabalho está pausado"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ainda não há informações"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ro/strings.xml b/SafetyCenter/Resources/shared_res/values-ro/strings.xml
index 9ce4e29c2..8fa57dcb4 100644
--- a/SafetyCenter/Resources/shared_res/values-ro/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ro/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Se scanează"</string>
<string name="loading_summary" msgid="3740846439782713910">"Se verifică setările dispozitivului…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Pare în regulă"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nu s-au găsit probleme"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Sfat disponibil}few{Sfaturi disponibile}other{Sfaturi disponibile}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nu s-au găsit probleme"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Vezi recomandarea}few{Vezi recomandările}other{Vezi recomandările}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Măsură luată}few{Măsuri luate}other{Măsuri luate}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Verifică setările"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Verifică lista de setări"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"S-au găsit riscuri potențiale"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Riscuri descoperite"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Contul poate fi în pericol"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Contul este în pericol"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Vezi alerta mai jos}few{Vezi alertele mai jos}other{Vezi alertele mai jos}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Cont în pericol"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Vezi alerta}few{Vezi alertele}other{Vezi alertele}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Pagina nu s-a putut deschide"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Nu s-a putut rezolva alerta"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nu s-au putut actualiza setările"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nu s-a putut verifica setarea}few{Nu s-au putut verifica setările}other{Nu s-au putut verifica setările}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profilul de serviciu este întrerupt"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Nu există informații încă"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ru/strings.xml b/SafetyCenter/Resources/shared_res/values-ru/strings.xml
index 9e3906a15..b72d9b0f0 100644
--- a/SafetyCenter/Resources/shared_res/values-ru/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ru/strings.xml
@@ -20,11 +20,11 @@
<string name="scanning_title" msgid="5424849039854311398">"Поиск"</string>
<string name="loading_summary" msgid="3740846439782713910">"Проверка настроек устройства…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Всё в порядке"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Угроз не обнаружено"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Доступен совет}one{Доступны советы}few{Доступны советы}many{Доступны советы}other{Доступны советы}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Проблем не найдено"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Посмотрите рекомендацию}one{Посмотрите рекомендации}few{Посмотрите рекомендации}many{Посмотрите рекомендации}other{Посмотрите рекомендации}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Выполнено действие}one{Выполнены действия}few{Выполнены действия}many{Выполнены действия}other{Выполнены действия}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Проверьте настройки"</string>
- <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Изучите список настроек"</string>
+ <string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Просмотрите список настроек"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"Устройство может быть под угрозой"</string>
<string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"Устройство под угрозой"</string>
<string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"Ваши данные могут быть под угрозой"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Обнаружены потенциальные риски"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Обнаружены риски"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Аккаунт может быть под угрозой"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Аккаунт под угрозой"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ознакомьтесь с оповещением ниже}one{Ознакомьтесь с оповещениями ниже}few{Ознакомьтесь с оповещениями ниже}many{Ознакомьтесь с оповещениями ниже}other{Ознакомьтесь с оповещениями ниже}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Аккаунт под угрозой"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Посмотрите оповещение}one{Посмотрите оповещения}few{Посмотрите оповещения}many{Посмотрите оповещения}other{Посмотрите оповещения}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Не удалось открыть страницу."</string>
<string name="resolving_action_error" msgid="371968886143262375">"Не удалось устранить проблему."</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Не удалось обновить настройки"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Не удалось проверить параметр}one{Не удалось проверить параметры}few{Не удалось проверить параметры}many{Не удалось проверить параметры}other{Не удалось проверить параметры}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Действие рабочего профиля приостановлено."</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Данных пока нет"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-si/strings.xml b/SafetyCenter/Resources/shared_res/values-si/strings.xml
index f023a038b..1ee63199f 100644
--- a/SafetyCenter/Resources/shared_res/values-si/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-si/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"ස්කෑන් කෙරේ"</string>
<string name="loading_summary" msgid="3740846439782713910">"උපාංග සැකසීම් පරීක්ෂා කරමින්…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"හොඳ බව පෙනේ"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ගැටලු හමු වූයේ නැත"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{ඉඟිය තිබේ}one{ඉඟි තිබේ}other{ඉඟි තිබේ}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ගැටලු හමු නොවිණි"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{නිර්දේශය බලන්න}one{නිර්දේශ බලන්න}other{නිර්දේශ බලන්න}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ගත් ක්‍රියාමාර්ගය}one{ගත් ක්‍රියාමාර්ග}other{ගත් ක්‍රියාමාර්ග}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"සැකසීම් සමාලෝචනය කරන්න"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"සැකසීම් ලැයිස්තුව පරීක්ෂා කරන්න"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"විය හැකි අවදානම් හමු විය"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"අවදානම් හමු විය"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ගිණුම අවදානමේ තිබිය හැක"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ගිණුම අවදානමේ පවතී"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{පහත ඇඟවීම බලන්න}one{පහත ඇඟවීම් බලන්න}other{පහත ඇඟවීම් බලන්න}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ගිණුම අවදානමේ ඇත"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ඇඟවීම බලන්න}one{ඇඟවීම් බලන්න}other{ඇඟවීම් බලන්න}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"පිටුව විවෘත කළ නොහැකි විය"</string>
<string name="resolving_action_error" msgid="371968886143262375">"ඇඟවීම විසඳිය නොහැකි විය"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"සැකසීම් නැවුම් කිරීමට නොහැකි විය"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{සැකසීම පරීක්ෂා කිරීමට නොහැකි විය}one{සැකසීම් පරීක්ෂා කිරීමට නොහැකි විය}other{සැකසීම් පරීක්ෂා කිරීමට නොහැකි විය}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"කාර්යාල පැතිකඩ විරාම කර ඇත"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"තවම තතු නැත"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sk/strings.xml b/SafetyCenter/Resources/shared_res/values-sk/strings.xml
index 83dfc416a..905c3ffe5 100644
--- a/SafetyCenter/Resources/shared_res/values-sk/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sk/strings.xml
@@ -19,9 +19,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scanning_title" msgid="5424849039854311398">"Kontroluje sa"</string>
<string name="loading_summary" msgid="3740846439782713910">"Kontrolujú sa nastavenia zariadenia…"</string>
- <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Je to v poriadku"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nenašli sa žiadne problémy"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{K dispozícii je tip}few{K dispozícii sú tipy}many{Tips available}other{K dispozícii sú tipy}}"</string>
+ <string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Všetko v poriadku"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nenašli sa žiadne problémy"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Zobraziť odporúčanie}few{Zobraziť odporúčania}many{See recommendations}other{Zobraziť odporúčania}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Bola vykonaná akcia}few{Boli vykonané akcie}many{Actions taken}other{Boli vykonané akcie}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Kontrola nastavení"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kontrolný zoznam nastavení"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Boli nájdené potenciálne riziká"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Boli nájdené riziká"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Účet môže byť ohrozený"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Účet je ohrozený"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Prečítajte si upozornenie nižšie}few{Prečítajte si upozornenia nižšie}many{See alerts below}other{Prečítajte si upozornenia nižšie}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Účet je ohrozený"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Zobraziť upozornenie}few{Zobraziť upozornenia}many{See alerts}other{Zobraziť upozornenia}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Stránku sa nepodarilo otvoriť"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Upozornenie sa nepodarilo vyriešiť"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nastavenia sa nepodarilo obnoviť"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nastavenie sa nepodarilo skontrolovať}few{Nastavenia sa nepodarilo skontrolovať}many{Nastavenia sa nepodarilo skontrolovať}other{Nastavenia sa nepodarilo skontrolovať}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Pracovný profil je pozastavený"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Zatiaľ žiadne informácie"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sl/strings.xml b/SafetyCenter/Resources/shared_res/values-sl/strings.xml
index c66bfa02b..4502b63fd 100644
--- a/SafetyCenter/Resources/shared_res/values-sl/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sl/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Pregledovanje"</string>
<string name="loading_summary" msgid="3740846439782713910">"Preverjanje nastavitev naprave …"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Videti je v redu"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Ni težav."</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Na voljo je nasvet.}one{Na voljo so nasveti.}two{Na voljo so nasveti.}few{Na voljo so nasveti.}other{Na voljo so nasveti.}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Najdena ni bila nobena težava."</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Ogled priporočila}one{Ogled priporočil}two{Ogled priporočil}few{Ogled priporočil}other{Ogled priporočil}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Dejanje je bilo izvršeno.}one{Dejanja so bila izvršena.}two{Dejanja so bila izvršena.}few{Dejanja so bila izvršena.}other{Dejanja so bila izvršena.}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Pregled nastavitev"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Seznam za preverjanje nastavitev"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Najdena so morebitna tveganja"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Najdena so tveganja"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Račun je morda ogrožen"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Račun je ogrožen"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Oglejte si spodnje opozorilo.}one{Oglejte si spodnja opozorila.}two{Oglejte si spodnja opozorila.}few{Oglejte si spodnja opozorila.}other{Oglejte si spodnja opozorila.}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Račun je ogrožen"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Ogled opozorila}one{Ogled opozoril}two{Ogled opozoril}few{Ogled opozoril}other{Ogled opozoril}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Strani ni bilo mogoče odpreti."</string>
<string name="resolving_action_error" msgid="371968886143262375">"Opozorila ni bilo mogoče odpraviti."</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Nastavitev ni bilo mogoče osvežiti."</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Nastavitve ni bilo mogoče preveriti.}one{Nastavitve ni bilo mogoče preveriti.}two{Nastavitev ni bilo mogoče preveriti.}few{Nastavitev ni bilo mogoče preveriti.}other{Nastavitev ni bilo mogoče preveriti.}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Delovni profil je začasno zaustavljen."</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ni še nobenega podatka."</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sq/strings.xml b/SafetyCenter/Resources/shared_res/values-sq/strings.xml
index 99336807a..0e4981d2f 100644
--- a/SafetyCenter/Resources/shared_res/values-sq/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sq/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Po skanohet"</string>
<string name="loading_summary" msgid="3740846439782713910">"Po kontrollohen cilësimet pajisjes…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Duket mirë"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Nuk u gjetën probleme"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Ofrohet këshillë}other{Ofrohen këshilla}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Nuk u gjet asnjë problem"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Shiko rekomandimin}other{Shiko rekomandimet}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Masa e marrë}other{Masat e marra}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Rishiko cilësimet"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kontrollo listën e cilësimeve"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"U gjetën rreziqe të mundshme"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"U gjetën rreziqe"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Llogaria mund të jetë në rrezik"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Llogaria është në rrezik"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Shiko sinjalizimin më poshtë}other{Shiko sinjalizimet më poshtë}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Llogaria në rrezik"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Shiko sinjalizimin}other{Shiko sinjalizimet}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Faqja nuk mund të hapej"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Sinjalizimi nuk mund të zgjidhej"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Cilësimet nuk mund të rifreskoheshin"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Cilësimi nuk mund të kontrollohej}other{Cilësimet nuk mund të kontrolloheshin}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Profili i punës është në pauzë"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Nuk ka ende informacione"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sr/strings.xml b/SafetyCenter/Resources/shared_res/values-sr/strings.xml
index bf82a6785..e7a5db675 100644
--- a/SafetyCenter/Resources/shared_res/values-sr/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sr/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Скенира се"</string>
<string name="loading_summary" msgid="3740846439782713910">"Проверавамо подешавања уређаја…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Све је у реду"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Није пронађен ниједан проблем"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Доступан је савет}one{Доступни су савети}few{Доступни су савети}other{Доступни су савети}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Није пронађен ниједан проблем"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Прикажи препоруку}one{Прикажи препоруке}few{Прикажи препоруке}other{Прикажи препоруке}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Предузета радња}one{Предузете радње}few{Предузете радње}other{Предузете радње}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Прегледајте подешавања"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Проверите листу подешавања"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Пронађени су потенцијални ризици"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Пронађени су ризици"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Налог је можда угрожен"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Налог је угрожен"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Погледајте упозорење испод}one{Погледајте упозорења испод}few{Погледајте упозорења испод}other{Погледајте упозорења испод}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Налог је угрожен"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Прикажи обавештење}one{Прикажи обавештења}few{Прикажи обавештења}other{Прикажи обавештења}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Отварање странице није успело"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Решавање обавештења није успело"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Освежавање подешавања није успело"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Провера подешавања није успела}one{Провера подешавања није успела}few{Провера подешавања није успела}other{Провера подешавања није успела}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Пословни профил је паузиран"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Још нема информација"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sv/strings.xml b/SafetyCenter/Resources/shared_res/values-sv/strings.xml
index f31413a2d..e7773a565 100644
--- a/SafetyCenter/Resources/shared_res/values-sv/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sv/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Genomsöker"</string>
<string name="loading_summary" msgid="3740846439782713910">"Kontrollerar enhetsinställningarna …"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Det ser bra ut"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Inga problem hittades"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Det finns ett tips}other{Det finns tips}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Inga problem hittades"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Se rekommendation}other{Se rekommendationer}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Åtgärd har vidtagits}other{Åtgärder har vidtagits}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Granska inställningarna"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kontrollera listan med inställningar"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potentiella risker har upptäckts"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risker har upptäckts"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Kontot kan vara i fara"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Kontot är i fara"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Se avisering nedan}other{Se aviseringar nedan}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Kontot är i fara"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Se varning}other{Se varningar}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Det gick inte att öppna sidan"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Det gick inte att åtgärda varningen"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Det gick inte att uppdatera inställningarna"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Det gick inte att kontrollera inställningen}other{Det gick inte att kontrollera inställningarna}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Jobbprofilen är pausad"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Ingen information än"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-sw/strings.xml b/SafetyCenter/Resources/shared_res/values-sw/strings.xml
index 49310ca55..b78abb739 100644
--- a/SafetyCenter/Resources/shared_res/values-sw/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-sw/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Inakagua"</string>
<string name="loading_summary" msgid="3740846439782713910">"Inakagua mipangilio ya kifaa…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Kila kitu ki shwari"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Haikupata hitilafu yoyote"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Kidokezo kinapatikana}other{Vidokezo vinapatikana}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Hakuna hitilafu iliyopatikana"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Angalia pendekezo}other{Angalia mapendekezo}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Hatua imechukuliwa}other{Hatua zimechukuliwa}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Kagua mipangilio"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kagua orodha ya mipangilio"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Tumegundua hatari zinazoweza kutokea"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Tumegundua hatari"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Huenda akaunti iko hatarini"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Akaunti iko hatarini"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Angalia arifa hapo chini}other{Angalia arifa hapo chini}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Akaunti iko hatarini"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Angalia tahadhari}other{Angalia tahadhari}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Imeshindwa kufungua ukurasa"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Imeshindwa kutia alama kuwa arifa imeshughulikiwa"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Tumeshindwa kuonyesha upya mipangilio"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Imeshindwa kukagua mipangilio}other{Imeshindwa kukagua mipangilio}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Wasifu wa kazini umesimamishwa"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Bado hakuna maelezo"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ta/strings.xml b/SafetyCenter/Resources/shared_res/values-ta/strings.xml
index d0081c004..3acc13e92 100644
--- a/SafetyCenter/Resources/shared_res/values-ta/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ta/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"ஸ்கேன் செய்தல்"</string>
<string name="loading_summary" msgid="3740846439782713910">"சாதன அமைப்புகளைச் சரிபார்க்கிறது…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"எல்லாம் சரியாக உள்ளன"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"சிக்கல்கள் எதுவுமில்லை"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{உதவிக்குறிப்பு உள்ளது}other{உதவிக்குறிப்புகள் உள்ளன}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"சிக்கல்கள் எதுவுமில்லை"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{பரிந்துரையைப் பாருங்கள்}other{பரிந்துரைகளைப் பாருங்கள்}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{எடுக்கப்பட்ட நடவடிக்கை}other{எடுக்கப்பட்ட நடவடிக்கைகள்}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"அமைப்புகளைச் சரிபார்த்தல்"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"அமைப்புகள் பட்டியலைச் சரிபாருங்கள்"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"சாத்தியமுள்ள ஆபத்து கண்டறியப்பட்டன"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"ஆபத்துகள் கண்டறியப்பட்டுள்ளன"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"கணக்கு ஆபத்தில் இருக்கலாம்"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"கணக்கு ஆபத்தில் உள்ளது"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{கீழுள்ள விழிப்பூட்டலைப் பாருங்கள்}other{கீழுள்ள விழிப்பூட்டல்களைப் பாருங்கள்}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"கணக்கு ஆபத்தில் உள்ளது"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{விழிப்பூட்டலைப் பாருங்கள்}other{விழிப்பூட்டல்களைப் பாருங்கள்}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"பக்கத்தைத் திறக்க முடியவில்லை"</string>
<string name="resolving_action_error" msgid="371968886143262375">"எச்சரிக்கையைத் தீர்க்க முடியவில்லை"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"அமைப்புகளைப் புதுப்பிக்க முடியவில்லை"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{அமைப்பைச் சரிபார்க்க முடியவில்லை}other{அமைப்புகளைச் சரிபார்க்க முடியவில்லை}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"பணிக் கணக்கு இடைநிறுத்தப்பட்டது"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"தகவல்கள் எதுவுமில்லை"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-te/strings.xml b/SafetyCenter/Resources/shared_res/values-te/strings.xml
index 5dc26fb81..c9ecc0f23 100644
--- a/SafetyCenter/Resources/shared_res/values-te/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-te/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"స్కానింగ్"</string>
<string name="loading_summary" msgid="3740846439782713910">"పరికర సెట్టింగ్‌లను చెక్ చేస్తోంది…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"అంతా బాగానే ఉంది"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"సమస్యలు ఏవీ కనుగొనబడలేదు"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{చిట్కా అందుబాటులో ఉంది}other{చిట్కాలు అందుబాటులో ఉన్నాయి}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ఎటువంటి సమస్యలూ కనుగొనబడలేదు"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{సిఫార్సును చూడండి}other{సిఫార్సులను చూడండి}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{చర్య తీసుకోబడింది}other{చర్యలు తీసుకొనబడ్డాయి}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"సెట్టింగ్‌లను రివ్యూ చేయండి"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"సెట్టింగ్‌ల లిస్ట్‌ను చెక్ చేయండి"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"అవకాశం ఉన్న రిస్క్‌లు కనుగొనబడ్డాయి"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"రిస్క్‌లు కనుగొనబడ్డాయి"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"ఖాతా ప్రమాదంలో ఉండవచ్చు"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"ఖాతా ప్రమాదంలో ఉంది"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{కింద అలర్ట్‌ను చూడండి}other{కింద అలర్ట్‌లను చూడండి}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"ఖాతా ప్రమాదంలో ఉంది"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{అలర్ట్‌ను చూడండి}other{అలర్ట్‌లను చూడండి}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"పేజీని తెరవడం సాధ్యపడలేదు"</string>
<string name="resolving_action_error" msgid="371968886143262375">"అలర్ట్‌ను పరిష్కరించడం సాధ్యపడలేదు"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"సెట్టింగ్‌లను రిఫ్రెష్ చేయడం సాధ్యపడలేదు"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{సెట్టింగ్‌ను చెక్ చేయడం సాధ్యపడలేదు}other{సెట్టింగ్‌లను చెక్ చేయడం సాధ్యపడలేదు}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"వర్క్ ప్రొఫైల్ పాజ్ చేయబడింది"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ఇంకా ఏ సమాచారం లేదు"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-th/strings.xml b/SafetyCenter/Resources/shared_res/values-th/strings.xml
index 5ac8eac2f..f879c3ae4 100644
--- a/SafetyCenter/Resources/shared_res/values-th/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-th/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"การสแกน"</string>
<string name="loading_summary" msgid="3740846439782713910">"กำลังตรวจสอบการตั้งค่าอุปกรณ์…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ดูดีแล้ว"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"ไม่พบปัญหา"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{เคล็ดลับที่นำไปใช้ได้}other{เคล็ดลับที่นำไปใช้ได้}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"ไม่พบปัญหา"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{ดูคำแนะนำ}other{ดูคำแนะนำ}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{ดำเนินการแล้ว}other{ดำเนินการแล้ว}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ตรวจสอบการตั้งค่า"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ตรวจสอบรายการการตั้งค่า"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"พบความเสี่ยงที่อาจเกิดขึ้น"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"พบความเสี่ยง"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"บัญชีอาจมีความเสี่ยง"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"บัญชีมีความเสี่ยง"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ดูการแจ้งเตือนด้านล่าง}other{ดูการแจ้งเตือนด้านล่าง}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"บัญชีมีความเสี่ยง"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{ดูการแจ้งเตือน}other{ดูการแจ้งเตือน}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"เปิดหน้าไม่ได้"</string>
<string name="resolving_action_error" msgid="371968886143262375">"แก้ไขการแจ้งเตือนไม่ได้"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"รีเฟรชการตั้งค่าไม่ได้"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ไม่สามารถตรวจสอบการตั้งค่า}other{ไม่สามารถตรวจสอบการตั้งค่า}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"โปรไฟล์งานหยุดชั่วคราว"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ยังไม่มีข้อมูล"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-tl/strings.xml b/SafetyCenter/Resources/shared_res/values-tl/strings.xml
index 9426dd435..d2449116f 100644
--- a/SafetyCenter/Resources/shared_res/values-tl/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-tl/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Pag-scan"</string>
<string name="loading_summary" msgid="3740846439782713910">"Tinitingnan ang mga setting ng device…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Mukhang ayos"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Walang nakitang problema"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{May available na tip}one{May mga available na tip}other{May mga available na tip}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Walang nakitang isyu"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Tingnan ang rekomendasyon}one{Tingnan ang mga rekomendasyon}other{Tingnan ang mga rekomendasyon}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Ginawang pagkilos}one{Mga ginawang pagkilos}other{Mga ginawang pagkilos}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Suriin ang mga setting"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Tingnan ang listahan ng mga setting"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"May nakitang potensyal na panganib"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"May nakitang mga panganib"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Posibleng nanganganib ang account"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Nanganganib ang account"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Tingnan ang alerto sa ibaba}one{Tingnan ang mga alerto sa ibaba}other{Tingnan ang mga alerto sa ibaba}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Nanganganib ang account"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Tingnan ang alerto}one{Tingnan ang mga alerto}other{Tingnan ang mga alerto}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Hindi mabuksan ang page"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Hindi ma-resolve ang alerto"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Hindi ma-refresh ang mga setting"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Hindi masuri ang setting}one{Hindi masuri ang mga setting}other{Hindi masuri ang mga setting}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Naka-pause ang profile sa trabaho"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Wala pang impormasyon"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-tr/strings.xml b/SafetyCenter/Resources/shared_res/values-tr/strings.xml
index 55693a94b..69bf874dd 100644
--- a/SafetyCenter/Resources/shared_res/values-tr/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-tr/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Tarama"</string>
<string name="loading_summary" msgid="3740846439782713910">"Cihaz ayarları kontrol ediliyor…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"İyi görünüyor"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Sorun bulunmadı"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{İpucu mevcut}other{İpuçları mevcut}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Sorun bulunmadı"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Öneriye göz atın}other{Önerilere göz atın}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Gerçekleştirilen işlem}other{Gerçekleştirilen işlemler}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Ayarları inceleyin"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Ayarlar listesini kontrol edin"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Olası riskler bulundu"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Risk bulundu"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Hesap risk altında olabilir"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Hesap risk altında"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Aşağıdaki uyarıya bakın}other{Aşağıdaki uyarılara bakın}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Hesap risk altında"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Uyarıya göz atın}other{Uyarılara göz atın}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Sayfa açılamadı"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Uyarı sonlandırılamadı"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Ayarlar yenilenemedi"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Ayar kontrol edilemedi}other{Ayarlar kontrol edilemedi}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"İş profili duraklatıldı"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Henüz bilgi yok"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-uk/strings.xml b/SafetyCenter/Resources/shared_res/values-uk/strings.xml
index 8a9ef7221..44b304f80 100644
--- a/SafetyCenter/Resources/shared_res/values-uk/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-uk/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Пошук"</string>
<string name="loading_summary" msgid="3740846439782713910">"Перевіряємо налаштування пристрою…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Усе добре"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Проблем не знайдено"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Є порада}one{Є поради}few{Є поради}many{Є поради}other{Є поради}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Проблем не виявлено"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Перегляньте рекомендацію}one{Перегляньте рекомендації}few{Перегляньте рекомендації}many{Перегляньте рекомендації}other{Перегляньте рекомендації}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Вжито захід}one{Вжито заходів}few{Вжито заходів}many{Вжито заходів}other{Вжито заходів}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Перевірте налаштування"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Перегляньте список налаштувань"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Виявлено потенційні загрози безпеці"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Виявлено загрози безпеці"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Можлива загроза обліковому запису"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Обліковий запис під загрозою"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Перегляньте сповіщення нижче}one{Перегляньте сповіщення нижче}few{Перегляньте сповіщення нижче}many{Перегляньте сповіщення нижче}other{Перегляньте сповіщення нижче}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Обліковий запис під загрозою"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Перегляньте сповіщення}one{Перегляньте сповіщення}few{Перегляньте сповіщення}many{Перегляньте сповіщення}other{Перегляньте сповіщення}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Не вдалося відкрити сторінку"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Не вдалося закрити сповіщення"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Не вдалось оновити налаштування"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Не вдалося перевірити налаштування}one{Не вдалося перевірити налаштування}few{Не вдалося перевірити налаштування}many{Не вдалося перевірити налаштування}other{Не вдалося перевірити налаштування}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Робочий профіль призупинено"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Поки немає інформації"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-ur/strings.xml b/SafetyCenter/Resources/shared_res/values-ur/strings.xml
index 3ad7b8631..f0d791f1e 100644
--- a/SafetyCenter/Resources/shared_res/values-ur/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-ur/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"اسکین ہو رہا ہے"</string>
<string name="loading_summary" msgid="3740846439782713910">"آلے کی ترتیبات چیک کی جا رہی ہیں…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"ٹھیک لگ رہا ہے"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"کوئی مسئلہ نہیں پایا گيا"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{تجویز دستیاب ہے}other{تجاویز دستیاب ہیں}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"کوئی مسئلہ نہیں ملا"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{تجویز دیکھیں}other{تجاویز دیکھیں}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{کیا گیا اقدام}other{کیے گئے اقدامات}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"ترتیبات کا جائزہ لیں"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"ترتیبات کی فہرست چیک کریں"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"ممکنہ خطرات پائے گئے"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"خطرات پائے گئے"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"اکاؤنٹ خطرے میں ہو سکتا ہے"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"اکاؤنٹ خطرے میں ہے"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{ذیل میں الرٹ دیکھیں}other{ذیل میں الرٹس دیکھیں}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"اکاؤنٹ خطرے میں ہے"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{الرٹ دیکھیں}other{الرٹس دیکھیں}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"صفحہ نہیں کھل سکا"</string>
<string name="resolving_action_error" msgid="371968886143262375">"الرٹ حل نہیں ہو سکا"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"ترتیبات ریفریش نہیں کی جا سکی"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{ترتیب کی جانچ نہیں کی جا سکی}other{ترتیبات کی جانچ نہیں کی جا سکی}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"دفتری پروفائل روک دی گئی ہے"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"ابھی تک کوئی معلومات نہیں ہے"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-uz/strings.xml b/SafetyCenter/Resources/shared_res/values-uz/strings.xml
index d01559ead..a4b933eb9 100644
--- a/SafetyCenter/Resources/shared_res/values-uz/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-uz/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Tekshiruv"</string>
<string name="loading_summary" msgid="3740846439782713910">"Qurilma sozlamalari tekshirilmoqda…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Hammasi joyida"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Hech qanday muammo topilmadi"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Tavsiya bor}other{Tavsiyalar bor}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Hech qanday muammo topilmadi"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Tavsiya}other{Tavsiyalar}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Bajarilgan amal}other{Bajarilgan amallar}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Sozlamalarni tekshirish"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Sozlamalar roʻyxatini tekshirish"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"Xavf ostidasiz"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Potentsial xavflar topildi"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Xavflar topildi"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Hisob xavf ostida shekilli"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Hisob xavf ostida"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Ogohlantiruvni ochish}other{Ogohlantiruvlarni ochish}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Hisob xavf ostida boʻlishi mumkin"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Hisob xavf ostida"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Ogohlantirish}other{Ogohlantirishlar}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Sahifa ochilmadi"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Ogohlantirish hal qilinmadi"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Sozlamalar yangilanmadi"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Sozlama tekshirilmadi}other{Sozlamalar tekshirilmadi}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Ish profili pauzada"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Hali axborot olinmadi"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-vi/strings.xml b/SafetyCenter/Resources/shared_res/values-vi/strings.xml
index 6aa24cbaf..8bbffeb1b 100644
--- a/SafetyCenter/Resources/shared_res/values-vi/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-vi/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Quét"</string>
<string name="loading_summary" msgid="3740846439782713910">"Đang kiểm tra chế độ cài đặt của thiết bị…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Có vẻ ổn"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Không tìm thấy vấn đề nào"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Có mẹo cho bạn}other{Có mẹo cho bạn}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Không phát hiện thấy sự cố nào"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Xem đề xuất}other{Xem các đề xuất}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Hành động đã thực hiện}other{Hành động đã thực hiện}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Xem lại các chế độ cài đặt"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Kiểm tra danh sách cài đặt"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Đã phát hiện rủi ro tiềm ẩn"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Đã phát hiện rủi ro"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"Tài khoản có thể gặp rủi ro"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"Tài khoản đang gặp rủi ro"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Xem cảnh báo bên dưới}other{Xem cảnh báo bên dưới}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"Tài khoản đang gặp rủi ro"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Xem cảnh báo}other{Xem cảnh báo}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Không thể mở trang"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Không thể giải quyết vấn đề cảnh báo"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Không thể làm mới cài đặt"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Không kiểm tra được chế độ cài đặt}other{Không kiểm tra được các chế độ cài đặt}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Hồ sơ công việc của bạn đã bị tạm dừng"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Chưa có thông tin"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-zh-rCN/strings.xml b/SafetyCenter/Resources/shared_res/values-zh-rCN/strings.xml
index 4f0805d5f..bc59150b4 100644
--- a/SafetyCenter/Resources/shared_res/values-zh-rCN/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-zh-rCN/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"正在扫描"</string>
<string name="loading_summary" msgid="3740846439782713910">"正在检查设备设置…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"没问题"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"未发现问题"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{有可用的提示}other{有可用的提示}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"未发现任何问题"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{查看建议}other{查看建议}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{已采取措施}other{已采取措施}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"检查设置"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"请检查设置列表"</string>
@@ -35,12 +35,11 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"您目前有风险"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"发现潜在风险"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"发现风险"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"帐号可能存在风险"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"帐号存在风险"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{请查看下方提醒}other{请查看下方提醒}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"账号可能存在风险"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"账号存在风险"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{查看提醒}other{查看提醒}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"无法打开页面"</string>
<string name="resolving_action_error" msgid="371968886143262375">"无法解决提醒事项"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"无法刷新设置"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{无法检查设置}other{无法检查设置}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"工作资料已被暂停"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"尚无任何信息"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-zh-rHK/strings.xml b/SafetyCenter/Resources/shared_res/values-zh-rHK/strings.xml
index 35db195f7..a2f8f75a8 100644
--- a/SafetyCenter/Resources/shared_res/values-zh-rHK/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-zh-rHK/strings.xml
@@ -20,27 +20,26 @@
<string name="scanning_title" msgid="5424849039854311398">"正在掃瞄"</string>
<string name="loading_summary" msgid="3740846439782713910">"正在檢查裝置設定…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"沒有問題"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"未發現問題"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{有可用的提示}other{有可用的提示}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"未發現任何問題"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{查看建議}other{查看建議}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{已採取行動}other{已採取行動}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"檢查設定"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"查看設定清單"</string>
<string name="overall_severity_level_device_recommendation_title" msgid="5250040236433061827">"裝置可能存在風險"</string>
<string name="overall_severity_level_critical_device_warning_title" msgid="5901771721834272596">"裝置存在風險"</string>
- <string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"您的資料可能面臨風險"</string>
- <string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"您的資料正面臨風險"</string>
+ <string name="overall_severity_level_data_recommendation_title" msgid="1424269714861655302">"你的資料可能面臨風險"</string>
+ <string name="overall_severity_level_critical_data_warning_title" msgid="1012704126634698604">"你的資料正面臨風險"</string>
<string name="overall_severity_level_passwords_recommendation_title" msgid="8625105570296877719">"被盜用的密碼 (舊)"</string>
<string name="overall_severity_level_critical_passwords_warning_title" msgid="7859047988648851217">"被盜用的密碼 (新)"</string>
- <string name="overall_severity_level_personal_recommendation_title" msgid="5493814377982623779">"您可能面臨風險"</string>
- <string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"您正面臨風險"</string>
+ <string name="overall_severity_level_personal_recommendation_title" msgid="5493814377982623779">"你可能面臨風險"</string>
+ <string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"你正面臨風險"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"系統發現潛在風險"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"系統發現風險"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"帳戶可能面臨風險"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"裝置正面臨風險"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{查看下方的警示}other{查看下方的警示}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"帳戶可能存在風險"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"帳戶存在風險"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{查看警示}other{查看警示}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"無法開啟頁面"</string>
<string name="resolving_action_error" msgid="371968886143262375">"無法解除警示"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"無法重新整理設定"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{無法檢查設定}other{無法檢查設定}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"工作設定檔已暫停"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"暫時沒有資料"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-zh-rTW/strings.xml b/SafetyCenter/Resources/shared_res/values-zh-rTW/strings.xml
index 500a9d4a3..beb5af4a2 100644
--- a/SafetyCenter/Resources/shared_res/values-zh-rTW/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-zh-rTW/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"掃描"</string>
<string name="loading_summary" msgid="3740846439782713910">"正在檢查裝置設定…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"沒有問題"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"未發現問題"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{有可用的提示}other{有可用的提示}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"未發現任何問題"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{查看建議}other{查看建議}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{已採取行動}other{已採取行動}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"查看設定"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"檢查設定清單"</string>
@@ -35,16 +35,15 @@
<string name="overall_severity_level_critical_personal_warning_title" msgid="5070434468955164734">"你的帳戶有風險"</string>
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"發現潛在風險"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"發現風險"</string>
- <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"帳戶可能面臨風險"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"帳戶目前有風險"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{請查看下方警示}other{請查看下方警示}}"</string>
+ <string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"帳戶可能有風險"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"帳戶有風險"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{查看警示}other{查看警示}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"無法開啟網頁"</string>
<string name="resolving_action_error" msgid="371968886143262375">"無法解決警示"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"無法重新整理設定"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{無法檢查設定}other{無法檢查設定}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"工作資料夾已暫停"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"目前還沒有任何資訊"</string>
- <string name="notification_channel_group_name" msgid="7155072032524876859">"安全性與隱私"</string>
+ <string name="notification_channel_group_name" msgid="7155072032524876859">"安全性與隱私權"</string>
<string name="notification_channel_name_information" msgid="2966444432152990166">"建議"</string>
<string name="notification_channel_name_recommendation" msgid="7847408286580217922">"警告"</string>
<string name="notification_channel_name_critical_warning" msgid="5994320322108351769">"嚴重警告"</string>
diff --git a/SafetyCenter/Resources/shared_res/values-zu/strings.xml b/SafetyCenter/Resources/shared_res/values-zu/strings.xml
index 55588c363..21c358f15 100644
--- a/SafetyCenter/Resources/shared_res/values-zu/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values-zu/strings.xml
@@ -20,8 +20,8 @@
<string name="scanning_title" msgid="5424849039854311398">"Iyaskena"</string>
<string name="loading_summary" msgid="3740846439782713910">"Ihlola amasethingi edivayisi…"</string>
<string name="overall_severity_level_ok_title" msgid="2041250138727564565">"Kubukeka kukuhle"</string>
- <string name="overall_severity_level_ok_summary" msgid="7219520381757200598">"Azikho izinkinga ezitholiwe"</string>
- <string name="overall_severity_level_tip_summary" msgid="5582440812368113766">"{count,plural, =1{Ithiphu liyatholakala}one{Amathiphu ayatholakala}other{Amathiphu ayatholakala}}"</string>
+ <string name="overall_severity_level_ok_summary" msgid="383626536912856690">"Ayikho inkinga etholiwe"</string>
+ <string name="overall_severity_level_tip_summary" msgid="1935765582243024999">"{count,plural, =1{Bona isincomo}one{Bona izincomo}other{Bona izincomo}}"</string>
<string name="overall_severity_level_action_taken_summary" msgid="8064091657855656545">"{count,plural, =1{Isinyathelo sithathiwe}one{Izinyathelo zithathiwe}other{Izinyathelo zithathiwe}}"</string>
<string name="overall_severity_level_ok_review_title" msgid="1494321117696765360">"Buyekeza amasethingi"</string>
<string name="overall_severity_level_ok_review_summary" msgid="7743619617413076275">"Hlola uhlu lwamasethingi"</string>
@@ -36,11 +36,10 @@
<string name="overall_severity_level_safety_recommendation_title" msgid="4291797434760242793">"Izingozi ezingaba khona zitholakele"</string>
<string name="overall_severity_level_critical_safety_warning_title" msgid="6666640109779586868">"Izingozi ezitholakele"</string>
<string name="overall_severity_level_account_recommendation_title" msgid="2267542168734275090">"I-akhawunti ingaba sengozini"</string>
- <string name="overall_severity_level_critical_account_warning_title" msgid="4402278408972158353">"I-akhawunti isengcupheni"</string>
- <string name="overall_severity_n_alerts_summary" msgid="6527386677095695234">"{count,plural, =1{Bona isexwayiso ngezansi}one{Bona izexwayiso ngezansi}other{Bona izexwayiso ngezansi}}"</string>
+ <string name="overall_severity_level_critical_account_warning_title" msgid="1913235490583842004">"I-akhawunti isengozini"</string>
+ <string name="overall_severity_n_alerts_summary" msgid="3262010942295408403">"{count,plural, =1{Bona isixwayiso}one{Bona izixwayiso}other{Bona izixwayiso}}"</string>
<string name="redirecting_error" msgid="8146983632878233202">"Ayikwazanga ukuvula ikhasi"</string>
<string name="resolving_action_error" msgid="371968886143262375">"Ayikwazanga ukuxazulula isexwayiso"</string>
- <string name="refresh_timeout" msgid="251734999692581852">"Ayikwazanga ukuvuselela amasethingi"</string>
<string name="refresh_error" msgid="656062128422446177">"{count,plural, =1{Ayikwazanga ukuhlola isethingi}one{Ayikwazanga ukuhlola amasethingi}other{Ayikwazanga ukuhlola amasethingi}}"</string>
<string name="work_profile_paused" msgid="7037400224040869079">"Iphrofayela yomsebenzi iphunyuziwe"</string>
<string name="group_unknown_summary" msgid="6951386960814105641">"Alukho ulwazi okwamanje"</string>
diff --git a/SafetyCenter/Resources/shared_res/values/strings.xml b/SafetyCenter/Resources/shared_res/values/strings.xml
index f4f1b0201..2b231b55f 100644
--- a/SafetyCenter/Resources/shared_res/values/strings.xml
+++ b/SafetyCenter/Resources/shared_res/values/strings.xml
@@ -94,9 +94,6 @@
<!-- An error shown to the user when we failed to resolve an alert that they attempted to resolve directly from the Safety Center screen [CHAR LIMIT=50] -->
<string name="resolving_action_error">Couldn\’t resolve alert</string>
- <!-- An error shown to the user when we failed to refresh the overall Safety Center status. This happens when at least one safety signal did not get back to Safety Center within an arbitrary timeout [CHAR LIMIT=50] -->
- <string name="refresh_timeout">Couldn\’t refresh settings</string>
-
<!-- An error shown to the user when we failed to refresh the status of one or more Safety Center entries. The number of entries is used as a parameter to format the error [CHAR LIMIT=60] -->
<string name="refresh_error">{count, plural,
=1 {Couldn\’t check setting}
diff --git a/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesApk.java b/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesApk.java
new file mode 100644
index 000000000..fe0908ea0
--- /dev/null
+++ b/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesApk.java
@@ -0,0 +1,353 @@
+/*
+ * 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.safetycenter.resources;
+
+import static java.util.Objects.requireNonNull;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.util.Log;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.VisibleForTesting;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * A class to access Safety Center resources that need to be fetched from a dedicated APK.
+ *
+ * <p>You must check whether Safety Center is enabled or the value returned by {@link #init()} prior
+ * to interacting with this class. Failure to do so may cause an {@link IllegalStateException} if
+ * the resources APK cannot be accessed.
+ *
+ * <p>This class isn't thread safe. Thread safety must be handled by the caller, or this may cause
+ * the resources APK {@link Context} to be initialized multiple times.
+ */
+public final class SafetyCenterResourcesApk {
+
+ private static final String TAG = "SafetyCenterResApk";
+
+ /** Intent action that is used to identify the Safety Center resources APK */
+ private static final String RESOURCES_APK_ACTION =
+ "com.android.safetycenter.intent.action.SAFETY_CENTER_RESOURCES_APK";
+
+ /** Permission APEX name */
+ private static final String APEX_MODULE_NAME = "com.android.permission";
+
+ /**
+ * The path where the Permission apex is mounted. Current value = "/apex/com.android.permission"
+ */
+ private static final String APEX_MODULE_PATH =
+ new File("/apex", APEX_MODULE_NAME).getAbsolutePath();
+
+ /** Raw XML config resource name */
+ private static final String CONFIG_NAME = "safety_center_config";
+
+ private final Context mContext;
+
+ /** Intent action that is used to identify the Safety Center resources APK */
+ private final String mResourcesApkAction;
+
+ /** The path where the Safety Center resources APK is expected to be installed */
+ private final String mResourcesApkPath;
+
+ /** Specific flags used for retrieving resolve info. */
+ private final int mFlags;
+
+ /**
+ * Whether we should fallback with an empty string / null values when calling the methods of
+ * this class for a resource that does not exist.
+ */
+ private final boolean mShouldFallbackIfNamedResourceNotFound;
+
+ // Cached context from the resources APK.
+ @Nullable private Context mResourcesApkContext;
+
+ public SafetyCenterResourcesApk(Context context) {
+ this(context, /* shouldFallbackIfNamedResourceNotFound */ true);
+ }
+
+ private SafetyCenterResourcesApk(
+ Context context, boolean shouldFallbackIfNamedResourceNotFound) {
+ this(
+ context,
+ RESOURCES_APK_ACTION,
+ APEX_MODULE_PATH,
+ PackageManager.MATCH_SYSTEM_ONLY,
+ shouldFallbackIfNamedResourceNotFound);
+ }
+
+ @VisibleForTesting
+ SafetyCenterResourcesApk(
+ Context context,
+ String resourcesApkAction,
+ String resourcesApkPath,
+ int flags,
+ boolean shouldFallbackIfNamedResourceNotFound) {
+ mContext = requireNonNull(context);
+ mResourcesApkAction = requireNonNull(resourcesApkAction);
+ mResourcesApkPath = requireNonNull(resourcesApkPath);
+ mFlags = flags;
+ mShouldFallbackIfNamedResourceNotFound = shouldFallbackIfNamedResourceNotFound;
+ }
+
+ /** Creates a new {@link SafetyCenterResourcesApk} for testing. */
+ @VisibleForTesting
+ public static SafetyCenterResourcesApk forTests(Context context) {
+ return new SafetyCenterResourcesApk(
+ context, /* shouldFallbackIfNamedResourceNotFound */ false);
+ }
+
+ /**
+ * Initializes the resources APK {@link Context}, and returns whether this was successful.
+ *
+ * <p>This call is optional as this can also be lazily instantiated. It can be used to ensure
+ * that the resources APK context is loaded prior to interacting with this class. This
+ * initialization code needs to run in the same user as the provided base {@link Context}. This
+ * may not be the case with a binder call, which is why it can be more appropriate to do this
+ * explicitly.
+ */
+ public boolean init() {
+ mResourcesApkContext = loadResourcesApkContext();
+ return mResourcesApkContext != null;
+ }
+
+ /**
+ * Returns the {@link Context} of the Safety Center resources APK.
+ *
+ * <p>Throws an {@link IllegalStateException} if the resources APK is not available
+ */
+ public Context getContext() {
+ if (mResourcesApkContext != null) {
+ return mResourcesApkContext;
+ }
+
+ mResourcesApkContext = loadResourcesApkContext();
+ if (mResourcesApkContext == null) {
+ throw new IllegalStateException("Resources APK context not found");
+ }
+
+ return mResourcesApkContext;
+ }
+
+ @Nullable
+ private Context loadResourcesApkContext() {
+ List<ResolveInfo> resolveInfos =
+ mContext.getPackageManager()
+ .queryIntentActivities(new Intent(mResourcesApkAction), mFlags);
+
+ if (resolveInfos.size() > 1) {
+ // multiple apps found, log a warning, but continue
+ Log.w(TAG, "Found > 1 APK that can resolve Safety Center resources APK intent:");
+ final int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ Log.w(
+ TAG,
+ String.format(
+ "- pkg:%s at:%s",
+ resolveInfo.activityInfo.applicationInfo.packageName,
+ resolveInfo.activityInfo.applicationInfo.sourceDir));
+ }
+ }
+
+ ResolveInfo info = null;
+ // Assume the first good ResolveInfo is the one we're looking for
+ final int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ if (!resolveInfo.activityInfo.applicationInfo.sourceDir.startsWith(mResourcesApkPath)) {
+ // skip apps that don't live in the Permission apex
+ continue;
+ }
+ info = resolveInfo;
+ break;
+ }
+
+ if (info == null) {
+ // Resource APK not loaded yet, print a stack trace to see where this is called from
+ Log.e(TAG, "Could not find Safety Center resources APK", new IllegalStateException());
+ return null;
+ }
+
+ String resourcesApkPkgName = info.activityInfo.applicationInfo.packageName;
+ Log.i(TAG, "Found Safety Center resources APK at: " + resourcesApkPkgName);
+ return getPackageContext(resourcesApkPkgName);
+ }
+
+ @Nullable
+ private Context getPackageContext(String packageName) {
+ try {
+ return mContext.createPackageContext(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Failed to load package context for: " + packageName, e);
+ }
+ return null;
+ }
+
+ /** Calls {@link Context#getResources()} for the resources APK {@link Context}. */
+ public Resources getResources() {
+ return getContext().getResources();
+ }
+
+ /**
+ * Returns the raw XML resource representing the Safety Center configuration file from the
+ * Safety Center resources APK.
+ */
+ @Nullable
+ public InputStream getSafetyCenterConfig() {
+ return getSafetyCenterConfig(CONFIG_NAME);
+ }
+
+ @VisibleForTesting
+ @Nullable
+ InputStream getSafetyCenterConfig(String configName) {
+ int resId = getResIdAndMaybeThrowIfNull(configName, "raw");
+ if (resId == Resources.ID_NULL) {
+ return null;
+ }
+ return getResources().openRawResource(resId);
+ }
+
+ /** Calls {@link Context#getString(int)} for the resources APK {@link Context}. */
+ public String getString(@StringRes int stringId) {
+ return getContext().getString(stringId);
+ }
+
+ /** Same as {@link #getString(int)} but with the given {@code formatArgs}. */
+ public String getString(@StringRes int stringId, Object... formatArgs) {
+ return getContext().getString(stringId, formatArgs);
+ }
+
+ /**
+ * Returns the {@link String} with the given resource name.
+ *
+ * <p>If the {@link String} cannot be accessed, returns {@code ""} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
+ */
+ public String getStringByName(String name) {
+ int resId = getResIdAndMaybeThrowIfNull(name, "string");
+ if (resId == Resources.ID_NULL) {
+ return "";
+ }
+ return getString(resId);
+ }
+
+ /** Same as {@link #getStringByName(String)} but with the given {@code formatArgs}. */
+ public String getStringByName(String name, Object... formatArgs) {
+ int resId = getResIdAndMaybeThrowIfNull(name, "string");
+ if (resId == Resources.ID_NULL) {
+ return "";
+ }
+ return getString(resId, formatArgs);
+ }
+
+ /**
+ * Returns an optional {@link String} resource with the given {@code stringId}.
+ *
+ * <p>Returns {@code null} if {@code stringId} is equal to {@link Resources#ID_NULL}. Otherwise,
+ * throws a {@link Resources.NotFoundException}.
+ */
+ @Nullable
+ public String getOptionalString(@StringRes int stringId) {
+ if (stringId == Resources.ID_NULL) {
+ return null;
+ }
+ return getString(stringId);
+ }
+
+ /** Same as {@link #getOptionalString(int)} but with the given resource name rather than ID. */
+ @Nullable
+ public String getOptionalStringByName(String name) {
+ return getOptionalString(getResId(name, "string"));
+ }
+
+ /**
+ * Returns the {@link Drawable} with the given resource name.
+ *
+ * <p>If the {@link Drawable} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
+ *
+ * @param theme the theme used to style the drawable attributes, may be {@code null}
+ */
+ @Nullable
+ public Drawable getDrawableByName(String name, @Nullable Resources.Theme theme) {
+ int resId = getResIdAndMaybeThrowIfNull(name, "drawable");
+ if (resId == Resources.ID_NULL) {
+ return null;
+ }
+ return getResources().getDrawable(resId, theme);
+ }
+
+ /**
+ * Returns an {@link Icon} containing the {@link Drawable} with the given resource name.
+ *
+ * <p>If the {@link Drawable} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
+ */
+ @Nullable
+ public Icon getIconByDrawableName(String name) {
+ int resId = getResIdAndMaybeThrowIfNull(name, "drawable");
+ if (resId == Resources.ID_NULL) {
+ return null;
+ }
+ return Icon.createWithResource(getContext().getPackageName(), resId);
+ }
+
+ /**
+ * Returns the {@link ColorInt} with the given resource name.
+ *
+ * <p>If the {@link ColorInt} cannot be accessed, returns {@code null} or throws {@link
+ * Resources.NotFoundException} depending on {@link #mShouldFallbackIfNamedResourceNotFound}.
+ */
+ @ColorInt
+ @Nullable
+ public Integer getColorByName(String name) {
+ int resId = getResIdAndMaybeThrowIfNull(name, "color");
+ if (resId == Resources.ID_NULL) {
+ return null;
+ }
+ return getResources().getColor(resId, getContext().getTheme());
+ }
+
+ private int getResIdAndMaybeThrowIfNull(String name, String type) {
+ int resId = getResId(name, type);
+ if (resId != Resources.ID_NULL) {
+ return resId;
+ }
+ if (!mShouldFallbackIfNamedResourceNotFound) {
+ throw new Resources.NotFoundException();
+ }
+ Log.w(TAG, "Named " + type + " resource: " + name + " not found");
+ return resId;
+ }
+
+ private int getResId(String name, String type) {
+ // TODO(b/227738283): profile the performance of this operation and consider adding caching
+ // or finding some alternative solution.
+ return getResources().getIdentifier(name, type, getContext().getPackageName());
+ }
+}
diff --git a/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java b/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java
deleted file mode 100644
index 9a77296e2..000000000
--- a/SafetyCenter/ResourcesLib/java/com/android/safetycenter/resources/SafetyCenterResourcesContext.java
+++ /dev/null
@@ -1,403 +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 com.android.safetycenter.resources;
-
-import static java.util.Objects.requireNonNull;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.util.Log;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Nullable;
-import androidx.annotation.StringRes;
-import androidx.annotation.VisibleForTesting;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-
-/**
- * Wrapper for context to override getResources method. Resources for the Safety Center that need to
- * be fetched from the dedicated resources APK.
- */
-public class SafetyCenterResourcesContext extends ContextWrapper {
- private static final String TAG = "SafetyCenterResContext";
-
- /** Intent action that is used to identify the Safety Center resources APK */
- private static final String RESOURCES_APK_ACTION =
- "com.android.safetycenter.intent.action.SAFETY_CENTER_RESOURCES_APK";
-
- /** Permission APEX name */
- private static final String APEX_MODULE_NAME = "com.android.permission";
-
- /**
- * The path where the Permission apex is mounted. Current value = "/apex/com.android.permission"
- */
- private static final String APEX_MODULE_PATH =
- new File("/apex", APEX_MODULE_NAME).getAbsolutePath();
-
- /** Raw XML config resource name */
- private static final String CONFIG_NAME = "safety_center_config";
-
- /** Intent action that is used to identify the Safety Center resources APK */
- private final String mResourcesApkAction;
-
- /** The path where the Safety Center resources APK is expected to be installed */
- @Nullable private final String mResourcesApkPath;
-
- /** Raw XML config resource name */
- private final String mConfigName;
-
- /** Specific flags used for retrieving resolve info */
- private final int mFlags;
-
- /**
- * Whether we should fallback with an empty string when calling {@link #getStringByName} for a
- * string resource that does not exist.
- */
- private final boolean mShouldFallbackIfNamedResourceNotFound;
-
- // Cached package name and resources from the resources APK
- @Nullable private String mResourcesApkPkgName;
- @Nullable private AssetManager mAssetsFromApk;
- @Nullable private Resources mResourcesFromApk;
- @Nullable private Resources.Theme mThemeFromApk;
-
- public SafetyCenterResourcesContext(Context contextBase) {
- this(contextBase, /* shouldFallbackIfNamedResourceNotFound */ true);
- }
-
- private SafetyCenterResourcesContext(
- Context contextBase, boolean shouldFallbackIfNamedResourceNotFound) {
- this(
- contextBase,
- RESOURCES_APK_ACTION,
- APEX_MODULE_PATH,
- CONFIG_NAME,
- PackageManager.MATCH_SYSTEM_ONLY,
- shouldFallbackIfNamedResourceNotFound);
- }
-
- @VisibleForTesting
- SafetyCenterResourcesContext(
- Context contextBase,
- String resourcesApkAction,
- @Nullable String resourcesApkPath,
- String configName,
- int flags,
- boolean shouldFallbackIfNamedResourceNotFound) {
- super(contextBase);
- mResourcesApkAction = requireNonNull(resourcesApkAction);
- mResourcesApkPath = resourcesApkPath;
- mConfigName = requireNonNull(configName);
- mFlags = flags;
- mShouldFallbackIfNamedResourceNotFound = shouldFallbackIfNamedResourceNotFound;
- }
-
- /** Creates a new {@link SafetyCenterResourcesContext} for testing. */
- @VisibleForTesting
- public static SafetyCenterResourcesContext forTests(Context contextBase) {
- return new SafetyCenterResourcesContext(
- contextBase, /* shouldFallbackIfNamedResourceNotFound */ false);
- }
-
- /**
- * Initializes the {@link Context}'s {@link AssetManager}, {@link Resources} and {@link
- * Resources.Theme}.
- *
- * <p>This call is optional as this can also be lazily instantiated. This is useful to ensure
- * that resources are loaded prior to interacting with the {@link SafetyCenterResourcesContext},
- * as this code needs to run for the same user as the provided base {@link Context}; which may
- * not be the case with a binder call.
- */
- public void init() {
- mAssetsFromApk = getAssets();
- mResourcesFromApk = getResources();
- mThemeFromApk = getTheme();
- }
-
- /** Get the package name of the Safety Center resources APK. */
- @VisibleForTesting
- @Nullable
- String getResourcesApkPkgName() {
- if (mResourcesApkPkgName != null) {
- return mResourcesApkPkgName;
- }
-
- List<ResolveInfo> resolveInfos =
- getPackageManager().queryIntentActivities(new Intent(mResourcesApkAction), mFlags);
-
- if (resolveInfos.size() > 1) {
- // multiple apps found, log a warning, but continue
- Log.w(TAG, "Found > 1 APK that can resolve Safety Center resources APK intent:");
- final int resolveInfosSize = resolveInfos.size();
- for (int i = 0; i < resolveInfosSize; i++) {
- ResolveInfo resolveInfo = resolveInfos.get(i);
- Log.w(
- TAG,
- String.format(
- "- pkg:%s at:%s",
- resolveInfo.activityInfo.applicationInfo.packageName,
- resolveInfo.activityInfo.applicationInfo.sourceDir));
- }
- }
-
- ResolveInfo info = null;
- // Assume the first good ResolveInfo is the one we're looking for
- final int resolveInfosSize = resolveInfos.size();
- for (int i = 0; i < resolveInfosSize; i++) {
- ResolveInfo resolveInfo = resolveInfos.get(i);
- if (mResourcesApkPath != null
- && !resolveInfo.activityInfo.applicationInfo.sourceDir.startsWith(
- mResourcesApkPath)) {
- // skip apps that don't live in the Permission apex
- continue;
- }
- info = resolveInfo;
- break;
- }
-
- if (info == null) {
- // Resource APK not loaded yet, print a stack trace to see where this is called from
- Log.e(
- TAG,
- "Attempted to fetch resources before Safety Center resources APK is loaded!",
- new IllegalStateException());
- return null;
- }
-
- mResourcesApkPkgName = info.activityInfo.applicationInfo.packageName;
- Log.i(TAG, "Found Safety Center resources APK at: " + mResourcesApkPkgName);
- return mResourcesApkPkgName;
- }
-
- /**
- * Gets the raw XML resource representing the Safety Center configuration from the Safety Center
- * resources APK.
- */
- @Nullable
- public InputStream getSafetyCenterConfig() {
- String resourcePkgName = getResourcesApkPkgName();
- if (resourcePkgName == null) {
- return null;
- }
- Resources resources = getResources();
- if (resources == null) {
- return null;
- }
- int id = resources.getIdentifier(mConfigName, "raw", resourcePkgName);
- if (id == Resources.ID_NULL) {
- return null;
- }
- return resources.openRawResource(id);
- }
-
- /**
- * Returns an optional {@link String} resource from the given {@code stringId}.
- *
- * <p>Returns {@code null} if {@code stringId} is equal to {@link Resources#ID_NULL}. Otherwise,
- * throws a {@link Resources.NotFoundException} if the resource cannot be accessed.
- */
- @Nullable
- public String getOptionalString(@StringRes int stringId) {
- if (stringId == Resources.ID_NULL) {
- return null;
- }
- return getString(stringId);
- }
-
- /** Same as {@link #getOptionalString(int)} but with the given {@code formatArgs}. */
- @Nullable
- public String getOptionalString(@StringRes int stringId, Object... formatArgs) {
- if (stringId == Resources.ID_NULL) {
- return null;
- }
- return getString(stringId, formatArgs);
- }
-
- /** Same as {@link #getOptionalString(int)} but using the string name rather than ID. */
- @Nullable
- public String getOptionalStringByName(String name) {
- return getOptionalString(getStringRes(name));
- }
-
- /**
- * Gets a string resource by name from the Safety Center resources APK, and returns an empty
- * string if the resource does not exist (or throws a {@link Resources.NotFoundException} if
- * {@link #mShouldFallbackIfNamedResourceNotFound} is {@code false}).
- */
- public String getStringByName(String name) {
- int id = getStringRes(name);
- return maybeFallbackIfNamedResourceIsNull(name, getOptionalString(id));
- }
-
- /** Same as {@link #getStringByName(String)} but with the given {@code formatArgs}. */
- public String getStringByName(String name, Object... formatArgs) {
- int id = getStringRes(name);
- return maybeFallbackIfNamedResourceIsNull(name, getOptionalString(id, formatArgs));
- }
-
- private String maybeFallbackIfNamedResourceIsNull(String name, @Nullable String value) {
- if (value != null) {
- return value;
- }
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
- }
- Log.w(TAG, "String resource " + name + " not found");
- return "";
- }
-
- @StringRes
- private int getStringRes(String name) {
- return getResId(name, "string");
- }
-
- private int getResId(String name, String type) {
- String resourcePkgName = getResourcesApkPkgName();
- if (resourcePkgName == null) {
- return Resources.ID_NULL;
- }
- Resources resources = getResources();
- if (resources == null) {
- return Resources.ID_NULL;
- }
- // TODO(b/227738283): profile the performance of this operation and consider adding caching
- // or finding some alternative solution.
- return resources.getIdentifier(name, type, resourcePkgName);
- }
-
- @Nullable
- private Context getResourcesApkContext() {
- String name = getResourcesApkPkgName();
- if (name == null) {
- return null;
- }
- try {
- return createPackageContext(name, 0);
- } catch (PackageManager.NameNotFoundException e) {
- Log.wtf(TAG, "Failed to load resources", e);
- }
- return null;
- }
-
- /** Retrieve assets held in the Safety Center resources APK. */
- @Override
- @Nullable
- public AssetManager getAssets() {
- if (mAssetsFromApk == null) {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext != null) {
- mAssetsFromApk = resourcesApkContext.getAssets();
- }
- }
- return mAssetsFromApk;
- }
-
- /** Retrieve resources held in the Safety Center resources APK. */
- @Override
- @Nullable
- public Resources getResources() {
- if (mResourcesFromApk == null) {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext != null) {
- mResourcesFromApk = resourcesApkContext.getResources();
- }
- }
- return mResourcesFromApk;
- }
-
- /** Retrieve theme held in the Safety Center resources APK. */
- @Override
- @Nullable
- public Resources.Theme getTheme() {
- if (mThemeFromApk == null) {
- Context resourcesApkContext = getResourcesApkContext();
- if (resourcesApkContext != null) {
- mThemeFromApk = resourcesApkContext.getTheme();
- }
- }
- return mThemeFromApk;
- }
-
- /**
- * Gets a drawable resource by name from the Safety Center resources APK. Returns a null
- * drawable if the resource does not exist (or throws a {@link Resources.NotFoundException} if
- * {@link #mShouldFallbackIfNamedResourceNotFound} is {@code false}).
- *
- * @param name the identifier for this drawable resource
- * @param theme the theme used to style the drawable attributes, may be {@code null}
- */
- @Nullable
- public Drawable getDrawableByName(String name, @Nullable Resources.Theme theme) {
- int resId = getResId(name, "drawable");
- if (resId != Resources.ID_NULL) {
- return getResources().getDrawable(resId, theme);
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
- }
-
- Log.w(TAG, "Drawable resource " + name + " not found");
- return null;
- }
-
- /**
- * Returns an {@link Icon} instance containing a drawable with the given name. If no such
- * drawable exists, returns {@code null} or throws {@link Resources.NotFoundException}.
- */
- @Nullable
- public Icon getIconByDrawableName(String drawableResName) {
- int resId = getResId(drawableResName, "drawable");
- if (resId != Resources.ID_NULL) {
- return Icon.createWithResource(getResourcesApkPkgName(), resId);
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
- }
-
- Log.w(TAG, "Drawable resource " + drawableResName + " not found");
- return null;
- }
-
- /** Gets a color by resource name */
- @ColorInt
- @Nullable
- public Integer getColorByName(String name) {
- int resId = getResId(name, "color");
- if (resId != Resources.ID_NULL) {
- return getResources().getColor(resId, getTheme());
- }
-
- if (!mShouldFallbackIfNamedResourceNotFound) {
- throw new Resources.NotFoundException();
- }
-
- Log.w(TAG, "Color resource " + name + " not found");
- return null;
- }
-}
diff --git a/SafetyCenter/ResourcesLib/tests/AndroidTest.xml b/SafetyCenter/ResourcesLib/tests/AndroidTest.xml
index 6dcfb0362..e15ecf22a 100644
--- a/SafetyCenter/ResourcesLib/tests/AndroidTest.xml
+++ b/SafetyCenter/ResourcesLib/tests/AndroidTest.xml
@@ -19,7 +19,7 @@
<configuration description="Runs unit tests for the Safety Center ResourcesLib library.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-instrumentation" />
- <option name="test-tag" value="SafetyCenterConfigTests" />
+ <option name="test-tag" value="SafetyCenterResourcesLibTests" />
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk33ModuleController" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
diff --git a/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt b/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt
new file mode 100644
index 000000000..3b1246497
--- /dev/null
+++ b/SafetyCenter/ResourcesLib/tests/SafetyCenterResourcesLibTestResources/res/raw/safety_center_config.txt
@@ -0,0 +1 @@
+TEST \ No newline at end of file
diff --git a/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesApkTest.kt b/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesApkTest.kt
new file mode 100644
index 000000000..b52595b13
--- /dev/null
+++ b/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesApkTest.kt
@@ -0,0 +1,440 @@
+/*
+ * 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.safetycenter.resources
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.res.Resources
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.lang.IllegalStateException
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SafetyCenterResourcesApkTest {
+ private val context: Context = getApplicationContext()
+
+ @Test
+ fun init_withValidInputs_returnsTrue() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val initialized = resourcesApk.init()
+
+ assertThat(initialized).isTrue()
+ }
+
+ @Test
+ fun init_withWrongAction_returnsFalse() {
+ val resourcesApk = newSafetyCenterResourcesApk(resourcesApkAction = "wrong")
+
+ val initialized = resourcesApk.init()
+
+ assertThat(initialized).isFalse()
+ }
+
+ @Test
+ fun init_withWrongPath_returnsFalse() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkPath = "/apex/com.android.permission")
+
+ val initialized = resourcesApk.init()
+
+ assertThat(initialized).isFalse()
+ }
+
+ @Test
+ fun init_withWrongFlags_returnsFalse() {
+ val resourcesApk = newSafetyCenterResourcesApk(flags = PackageManager.MATCH_SYSTEM_ONLY)
+
+ val initialized = resourcesApk.init()
+
+ assertThat(initialized).isFalse()
+ }
+
+ @Test
+ fun getContext_withValidInputs_returnsResourcesApkContext() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val resourcesApkContext = resourcesApk.context
+
+ assertThat(resourcesApkContext.packageName).isEqualTo(RESOURCES_APK_PKG_NAME)
+ }
+
+ @Test
+ fun getContext_withWrongAction_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(resourcesApkAction = "wrong")
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.context }
+ }
+
+ @Test
+ fun getContext_withWrongPath_throws() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkPath = "/apex/com.android.permission")
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.context }
+ }
+
+ @Test
+ fun getContext_withWrongFlags_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(flags = PackageManager.MATCH_SYSTEM_ONLY)
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.context }
+ }
+
+ @Test
+ fun getResources_withValidInputs_returnsResourcesApkContextResources() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val resources = resourcesApk.resources
+
+ assertThat(resources).isEqualTo(resourcesApk.context.resources)
+ }
+
+ @Test
+ fun getResources_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.resources }
+ }
+
+ @Test
+ fun getSafetyCenterConfig_withValidInputs_returnsConfigContent() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val config = resourcesApk.safetyCenterConfig
+ val configContent = config?.bufferedReader().use { it?.readText() }
+
+ assertThat(config).isNotNull()
+ assertThat(configContent).isEqualTo(CONFIG_CONTENT)
+ }
+
+ @Test
+ fun getSafetyCenterConfig_anotherValidConfigName_returnsConfigContent() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val config = resourcesApk.getSafetyCenterConfig(CONFIG_NAME)
+ val configContent = config?.bufferedReader().use { it?.readText() }
+
+ assertThat(config).isNotNull()
+ assertThat(configContent).isEqualTo(CONFIG_CONTENT)
+ }
+
+ @Test
+ fun getSafetyCenterConfig_invalidConfigNameWithFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getSafetyCenterConfig("wrong")).isNull()
+ }
+
+ @Test
+ fun getSafetyCenterConfig_invalidConfigNameWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getSafetyCenterConfig("wrong")
+ }
+ }
+
+ @Test
+ fun getSafetyCenterConfig_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.safetyCenterConfig }
+ }
+
+ @Test
+ fun getString_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val ok = resourcesApk.getString(android.R.string.ok)
+
+ assertThat(ok).isEqualTo("OK")
+ }
+
+ @Test
+ fun getString_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getString(android.R.string.ok)
+ }
+ }
+
+ @Test
+ fun getStringWithFormatArgs_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val ok = resourcesApk.getString(android.R.string.ok, "")
+
+ assertThat(ok).isEqualTo("OK")
+ }
+
+ @Test
+ fun getStringWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getString(android.R.string.ok, "")
+ }
+ }
+
+ @Test
+ fun getStringByName_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getStringByName("valid_string")).isEqualTo("I exist!")
+ }
+
+ @Test
+ fun getStringByName_invalidStringWithFallback_returnsEmptyString() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getStringByName("invalid_string")).isEqualTo("")
+ }
+
+ @Test
+ fun getStringByName_invalidStringWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getStringByName("invalid_string")
+ }
+ }
+
+ @Test
+ fun getStringByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getStringByName("valid_string")
+ }
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getStringByName("valid_string", "")).isEqualTo("I exist!")
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_invalidStringWithFallback_returnsEmptyString() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getStringByName("invalid_string", "")).isEqualTo("")
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_invalidStringWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getStringByName("invalid_string", "")
+ }
+ }
+
+ @Test
+ fun getStringByNameWithFormatArgs_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getStringByName("valid_string", "")
+ }
+ }
+
+ @Test
+ fun getOptionalString_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val ok = resourcesApk.getOptionalString(android.R.string.ok)
+
+ assertThat(ok).isEqualTo("OK")
+ }
+
+ @Test
+ fun getOptionalString_resourceIdNull_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ val string = resourcesApk.getOptionalString(Resources.ID_NULL)
+
+ assertThat(string).isNull()
+ }
+
+ @Test
+ fun getOptionalString_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getOptionalString(android.R.string.ok)
+ }
+ }
+
+ @Test
+ fun getOptionalStringByName_validString_returnsString() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getOptionalStringByName("valid_string")).isEqualTo("I exist!")
+ }
+
+ @Test
+ fun getOptionalStringByName_invalidStringWithFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getOptionalStringByName("invalid_string")).isNull()
+ }
+
+ @Test
+ fun getOptionalStringByName_invalidStringWithoutFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertThat(resourcesApk.getOptionalStringByName("invalid_string")).isNull()
+ }
+
+ @Test
+ fun getOptionalStringByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getOptionalStringByName("valid_string")
+ }
+ }
+
+ @Test
+ fun getDrawableByName_validDrawable_returnsDrawable() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getDrawableByName("valid_drawable", context.theme)).isNotNull()
+ }
+
+ @Test
+ fun getDrawableByName_invalidDrawableWithFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getDrawableByName("invalid_drawable", context.theme)).isNull()
+ }
+
+ @Test
+ fun getDrawableByName_invalidDrawableWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getDrawableByName("invalid_drawable", context.theme)
+ }
+ }
+
+ @Test
+ fun getDrawableByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getDrawableByName("valid_drawable", context.theme)
+ }
+ }
+
+ @Test
+ fun getIconByDrawableName_validDrawable_returnsIcon() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getIconByDrawableName("valid_drawable")).isNotNull()
+ }
+
+ @Test
+ fun getIconByDrawableName_invalidDrawableWithFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getIconByDrawableName("invalid_drawable")).isNull()
+ }
+
+ @Test
+ fun getIconByDrawableName_invalidDrawableWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getIconByDrawableName("invalid_drawable")
+ }
+ }
+
+ @Test
+ fun getIconByDrawableByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) {
+ resourcesApk.getIconByDrawableName("valid_drawable")
+ }
+ }
+
+ @Test
+ fun getColorByName_validColor_returnsColor() {
+ val resourcesApk = newSafetyCenterResourcesApk()
+
+ assertThat(resourcesApk.getColorByName("valid_color")).isNotNull()
+ }
+
+ @Test
+ fun getColorByName_invalidColorWithFallback_returnsNull() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = true)
+
+ assertThat(resourcesApk.getColorByName("invalid_color")).isNull()
+ }
+
+ @Test
+ fun getColorByName_invalidColorWithoutFallback_throws() {
+ val resourcesApk = newSafetyCenterResourcesApk(fallback = false)
+
+ assertFailsWith(Resources.NotFoundException::class) {
+ resourcesApk.getColorByName("invalid_color")
+ }
+ }
+
+ @Test
+ fun getColorByName_nullContext_throwsRegardlessOfFallback() {
+ val resourcesApk =
+ newSafetyCenterResourcesApk(resourcesApkAction = "wrong", fallback = true)
+
+ assertFailsWith(IllegalStateException::class) { resourcesApk.getColorByName("valid_color") }
+ }
+
+ private fun newSafetyCenterResourcesApk(
+ resourcesApkAction: String = RESOURCES_APK_ACTION,
+ resourcesApkPath: String = "",
+ flags: Int = 0,
+ fallback: Boolean = false
+ ) = SafetyCenterResourcesApk(context, resourcesApkAction, resourcesApkPath, flags, fallback)
+
+ companion object {
+ const val RESOURCES_APK_ACTION =
+ "com.android.safetycenter.tests.intent.action.SAFETY_CENTER_TEST_RESOURCES_APK"
+ const val RESOURCES_APK_PKG_NAME =
+ "com.android.safetycenter.tests.config.safetycenterresourceslibtestresources"
+ const val CONFIG_NAME = "test"
+ const val CONFIG_CONTENT = "TEST"
+ }
+}
diff --git a/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt b/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt
deleted file mode 100644
index 1a82460d2..000000000
--- a/SafetyCenter/ResourcesLib/tests/java/com/android/safetycenter/resources/SafetyCenterResourcesContextTest.kt
+++ /dev/null
@@ -1,226 +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 com.android.safetycenter.resources
-
-import android.content.Context
-import android.content.pm.PackageManager
-import android.content.res.Resources
-import androidx.test.core.app.ApplicationProvider.getApplicationContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.assertFailsWith
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class SafetyCenterResourcesContextTest {
- private val context: Context = getApplicationContext()
- private val theme: Resources.Theme? = context.theme
-
- @Test
- fun validDataWithValidInputs() {
- val resourcesContext =
- SafetyCenterResourcesContext(context, RESOURCES_APK_ACTION, null, CONFIG_NAME, 0, false)
-
- assertThat(resourcesContext.resourcesApkPkgName).isEqualTo(RESOURCES_APK_PKG_NAME)
-
- val configContent =
- resourcesContext.safetyCenterConfig?.bufferedReader().use { it?.readText() }
-
- assertThat(configContent).isEqualTo(CONFIG_CONTENT)
- assertThat(resourcesContext.assets).isNotNull()
- assertThat(resourcesContext.resources).isNotNull()
- assertThat(resourcesContext.theme).isNotNull()
- }
-
- @Test
- fun nullDataWithWrongAction() {
- val resourcesContext = createNewResourcesContext(resourcesApkAction = "wrong")
-
- assertThat(resourcesContext.resourcesApkPkgName).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
- }
-
- @Test
- fun nullDataWithWrongPath() {
- val resourcesContext =
- createNewResourcesContext(resourcesApkPath = "/apex/com.android.permission")
-
- assertThat(resourcesContext.resourcesApkPkgName).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
- }
-
- @Test
- fun nullDataWithWrongFlag() {
- val resourcesContext = createNewResourcesContext(flags = PackageManager.MATCH_SYSTEM_ONLY)
-
- assertThat(resourcesContext.resourcesApkPkgName).isNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNull()
- assertThat(resourcesContext.resources).isNull()
- assertThat(resourcesContext.theme).isNull()
- }
-
- @Test
- fun nullConfigWithWrongConfigName() {
- val resourcesContext = createNewResourcesContext(configName = "wrong")
-
- assertThat(resourcesContext.resourcesApkPkgName).isNotNull()
- assertThat(resourcesContext.safetyCenterConfig).isNull()
- assertThat(resourcesContext.assets).isNotNull()
- assertThat(resourcesContext.resources).isNotNull()
- assertThat(resourcesContext.theme).isNotNull()
- }
-
- @Test
- fun getStringByName_validString_returnsString() {
- val resourcesContext = createNewResourcesContext()
-
- assertThat(resourcesContext.getStringByName("valid_string")).isEqualTo("I exist!")
- }
-
- @Test
- fun getStringByName_invalidStringWithFallback_returnsEmptyString() {
- val resourcesContext = createNewResourcesContext(fallback = true)
-
- assertThat(resourcesContext.getStringByName("invalid_string")).isEqualTo("")
- }
-
- @Test
- fun getStringByName_invalidStringWithoutFallback_throws() {
- val resourcesContext = createNewResourcesContext(fallback = false)
-
- assertFailsWith(Resources.NotFoundException::class) {
- resourcesContext.getStringByName("invalid_string")
- }
- }
-
- @Test
- fun getOptionalStringByName_validString_returnsString() {
- val resourcesContext = createNewResourcesContext()
-
- assertThat(resourcesContext.getOptionalStringByName("valid_string")).isEqualTo("I exist!")
- }
-
- @Test
- fun getOptionalStringByName_invalidStringWithFallback_returnsNull() {
- val resourcesContext = createNewResourcesContext(fallback = true)
-
- assertThat(resourcesContext.getOptionalStringByName("invalid_string")).isNull()
- }
-
- @Test
- fun getOptionalStringByName_invalidStringWithoutFallback_returnsNull() {
- val resourcesContext = createNewResourcesContext(fallback = false)
-
- assertThat(resourcesContext.getOptionalStringByName("invalid_string")).isNull()
- }
-
- @Test
- fun getDrawableByName_validDrawable_returnsDrawable() {
- val resourcesContext = createNewResourcesContext()
-
- assertThat(resourcesContext.getDrawableByName("valid_drawable", theme)).isNotNull()
- }
-
- @Test
- fun getDrawableByName_invalidDrawableWithFallback_returnsNull() {
- val resourcesContext = createNewResourcesContext(fallback = true)
-
- assertThat(resourcesContext.getDrawableByName("invalid_drawable", theme)).isNull()
- }
-
- @Test
- fun getDrawableByName_invalidDrawableWithoutFallback_throws() {
- val resourcesContext = createNewResourcesContext(fallback = false)
-
- assertFailsWith(Resources.NotFoundException::class) {
- resourcesContext.getDrawableByName("invalid_drawable", theme)
- }
- }
-
- @Test
- fun getIconByDrawableName_validDrawable_returnsIcon() {
- val resourcesContext = createNewResourcesContext()
-
- assertThat(resourcesContext.getIconByDrawableName("valid_drawable")).isNotNull()
- }
-
- @Test
- fun getIconByDrawableName_invalidDrawableWithFallback_returnsNull() {
- val resourcesContext = createNewResourcesContext(fallback = true)
-
- assertThat(resourcesContext.getIconByDrawableName("invalid_drawable")).isNull()
- }
-
- @Test
- fun getIconByDrawableName_invalidDrawableWithoutFallback_throws() {
- val resourcesContext = createNewResourcesContext(fallback = false)
-
- assertFailsWith(Resources.NotFoundException::class) {
- resourcesContext.getIconByDrawableName("invalid_drawable")
- }
- }
-
- @Test
- fun getColorByName_validColor_returnsColor() {
- val resourcesContext = createNewResourcesContext()
-
- assertThat(resourcesContext.getColorByName("valid_color")).isNotNull()
- }
-
- @Test
- fun getColorByName_invalidColorWithFallback_returnsNull() {
- val resourcesContext = createNewResourcesContext(fallback = true)
-
- assertThat(resourcesContext.getColorByName("invalid_color")).isNull()
- }
-
- @Test
- fun getColorByName_invalidColorWithoutFallback_throws() {
- val resourcesContext = createNewResourcesContext(fallback = false)
-
- assertFailsWith(Resources.NotFoundException::class) {
- resourcesContext.getColorByName("invalid_color")
- }
- }
-
- private fun createNewResourcesContext(
- resourcesApkAction: String = RESOURCES_APK_ACTION,
- resourcesApkPath: String? = null,
- configName: String = CONFIG_NAME,
- flags: Int = 0,
- fallback: Boolean = false
- ) =
- SafetyCenterResourcesContext(
- context, resourcesApkAction, resourcesApkPath, configName, flags, fallback)
-
- companion object {
- const val RESOURCES_APK_ACTION =
- "com.android.safetycenter.tests.intent.action.SAFETY_CENTER_TEST_RESOURCES_APK"
- const val RESOURCES_APK_PKG_NAME =
- "com.android.safetycenter.tests.config.safetycenterresourceslibtestresources"
- const val CONFIG_NAME = "test"
- const val CONFIG_CONTENT = "TEST"
- }
-}
diff --git a/SafetyCenter/TEST_MAPPING b/SafetyCenter/TEST_MAPPING
index 5bc6abbc7..92397fe71 100644
--- a/SafetyCenter/TEST_MAPPING
+++ b/SafetyCenter/TEST_MAPPING
@@ -10,7 +10,13 @@
"path": "packages/modules/Permission/tests/functional/safetycenter/safetycenteractivity/"
},
{
+ "path": "packages/modules/Permission/tests/functional/safetycenter/subpages/"
+ },
+ {
"path": "packages/modules/Permission/tests/functional/safetycenter/singleuser/"
+ },
+ {
+ "path": "packages/modules/Permission/tests/hostside/safetycenter/"
}
]
}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index aa594e81e..689cd6865 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -6,7 +6,67 @@
],
"carpermission-presubmit" : [
{
- "name" : "CtsPermission3TestCases"
+ "name" : "CtsPermissionUiTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "carpermission-postsubmit" : [
+ {
+ "name" : "CtsPermissionUiTestCases",
+ "options": [
+ {
+ "include-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "alltests" : [
+ {
+ "name" : "PermissionControllerMockingTests"
+ },
+ {
+ "name" : "CtsPermissionTestCases"
+ },
+ {
+ "name" : "CtsPermissionUiTestCases"
+ },
+ {
+ "name" : "CtsPermissionPolicyTestCases"
+ },
+ {
+ "name" : "CtsAppOpsTestCases"
+ },
+ {
+ "name" : "CtsAppOps2TestCases"
+ },
+ {
+ "name": "PermissionControllerOutOfProcessTests"
+ },
+ {
+ "name" : "CtsRoleTestCases"
+ },
+ {
+ "name" : "CtsPermissionMultiUserTestCases"
+ },
+ {
+ "name": "CtsBackupTestCases",
+ "options": [
+ {
+ "include-filter": "android.backup.cts.PermissionTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsDevicePolicyManagerTestCases",
+ "options": [
+ {
+ "include-annotation": "com.android.cts.devicepolicy.annotations.PermissionsTest"
+ }
+ ]
}
]
}
diff --git a/flags/Android.bp b/flags/Android.bp
new file mode 100644
index 000000000..4f0241f91
--- /dev/null
+++ b/flags/Android.bp
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aconfig_declarations {
+ name: "permissions-aconfig-flags",
+ package: "com.android.permission.flags",
+ srcs: ["flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "permissions-aconfig-flags-lib",
+ aconfig_declarations: "permissions-aconfig-flags",
+ sdk_version: "system_current",
+ min_sdk_version: "30",
+ apex_available: [
+ "com.android.permission",
+ "test_com.android.permission",
+ ],
+ installable: false,
+ visibility: [
+ "//packages/modules/Permission:__subpackages__",
+ ],
+}
+
+java_library {
+ name: "permissions-flags-lib",
+ sdk_version: "system_current",
+ min_sdk_version: "30",
+ target_sdk_version: "34",
+ srcs: [
+ "java/**/*.java",
+ ],
+ static_libs: [
+ "permissions-aconfig-flags-lib",
+ ],
+ libs: [
+ "androidx.annotation_annotation",
+ "framework-annotations-lib",
+ ],
+ apex_available: [
+ "com.android.permission",
+ "test_com.android.permission",
+ ],
+ installable: false,
+ visibility: [
+ "//packages/modules/Permission:__subpackages__",
+ ],
+} \ No newline at end of file
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
new file mode 100644
index 000000000..050065368
--- /dev/null
+++ b/flags/flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.permission.flags"
+
+flag {
+ name: "voice_activation_op_enabled"
+ namespace: "permissions"
+ description: "This flag is used to support hotword activation events in privacy dashboard"
+ bug: "287264308"
+} \ No newline at end of file
diff --git a/flags/java/com/android/permission/flags/PermissionsFlags.java b/flags/java/com/android/permission/flags/PermissionsFlags.java
new file mode 100644
index 000000000..afab3fae5
--- /dev/null
+++ b/flags/java/com/android/permission/flags/PermissionsFlags.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 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.permission.flags;
+
+/** Class used for flags that do not work with aconfig tooling */
+public final class PermissionsFlags {}
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index de697f801..d8e7149f2 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -475,10 +475,10 @@ public final class RoleManager {
}
/**
- * Get package names of the applications holding the role for a default application.
+ * Get package name of the application holding the role for a default application.
* <p>
- * <strong>Note:</strong> Using this API requires holding
- * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}.
+ * Only roles describing default applications can be used with this method. They can have
+ * at most one holder.
*
* @param roleName the name of the default application role to get
*
@@ -506,8 +506,8 @@ public final class RoleManager {
/**
* Set a specific application as the default application.
* <p>
- * <strong>Note:</strong> Using this API requires holding
- * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}.
+ * Only roles describing default applications can be used with this method. They can have
+ * at most one holder.
*
* @param roleName the name of the default application role to set the role holder for
* @param packageName the package name of the application to set as the default application,
@@ -527,8 +527,8 @@ public final class RoleManager {
public void setDefaultApplication(@NonNull String roleName, @Nullable String packageName,
@ManageHoldersFlags int flags, @CallbackExecutor @NonNull Executor executor,
@NonNull Consumer<Boolean> callback) {
+ // Prior to Android V some devices might require the "packageName" to be non-null.
Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
- Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
try {
diff --git a/framework-s/java/android/app/role/TEST_MAPPING b/framework-s/java/android/app/role/TEST_MAPPING
index ce53dca05..01d04bea0 100644
--- a/framework-s/java/android/app/role/TEST_MAPPING
+++ b/framework-s/java/android/app/role/TEST_MAPPING
@@ -25,5 +25,24 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsRoleTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
+ }
+ ]
+ }
]
}
diff --git a/framework-s/java/android/safetycenter/SafetyCenter.md b/framework-s/java/android/safetycenter/SafetyCenter.md
index 9d3eb811f..ded7809a5 100644
--- a/framework-s/java/android/safetycenter/SafetyCenter.md
+++ b/framework-s/java/android/safetycenter/SafetyCenter.md
@@ -16,4 +16,5 @@
# Android safety for system developers
-TODO(b/203400159): Documentation
+See the [Android Preview docs](https://preview.source.android.com/docs/security/safety-center) for
+more information about Safety Center.
diff --git a/framework-s/java/android/safetycenter/SafetyCenterData.java b/framework-s/java/android/safetycenter/SafetyCenterData.java
index 720fb4997..7cae061a6 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterData.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterData.java
@@ -176,7 +176,8 @@ public final class SafetyCenterData implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public List<SafetyCenterIssue> getDismissedIssues() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mDismissedIssues;
}
@@ -191,7 +192,8 @@ public final class SafetyCenterData implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Bundle getExtras() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mExtras;
}
@@ -371,7 +373,8 @@ public final class SafetyCenterData implements Parcelable {
public Builder(@NonNull SafetyCenterStatus status) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mStatus = requireNonNull(status);
}
@@ -379,7 +382,8 @@ public final class SafetyCenterData implements Parcelable {
/** Creates a {@link Builder} with the values from the given {@link SafetyCenterData}. */
public Builder(@NonNull SafetyCenterData safetyCenterData) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetyCenterData);
mStatus = safetyCenterData.mStatus;
diff --git a/framework-s/java/android/safetycenter/SafetyCenterIssue.java b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
index cee872a3a..f10b56b83 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterIssue.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterIssue.java
@@ -190,7 +190,7 @@ public final class SafetyCenterIssue implements Parcelable {
public CharSequence getAttributionTitle() {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException(
- "Method not supported for versions lower than UPSIDE_DOWN_CAKE");
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mAttributionTitle;
}
@@ -237,7 +237,7 @@ public final class SafetyCenterIssue implements Parcelable {
public String getGroupId() {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException(
- "Method not supported for versions lower than UPSIDE_DOWN_CAKE");
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mGroupId;
}
@@ -404,7 +404,7 @@ public final class SafetyCenterIssue implements Parcelable {
public Builder setAttributionTitle(@Nullable CharSequence attributionTitle) {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException(
- "Method not supported for versions lower than UPSIDE_DOWN_CAKE");
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mAttributionTitle = attributionTitle;
return this;
@@ -461,7 +461,7 @@ public final class SafetyCenterIssue implements Parcelable {
public Builder setGroupId(@Nullable String groupId) {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException(
- "Method not supported for versions lower than UPSIDE_DOWN_CAKE");
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mGroupId = groupId;
return this;
@@ -599,7 +599,8 @@ public final class SafetyCenterIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public ConfirmationDialogDetails getConfirmationDialogDetails() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mConfirmationDialogDetails;
}
@@ -811,7 +812,8 @@ public final class SafetyCenterIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull Action action) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(action);
mId = action.mId;
@@ -890,7 +892,8 @@ public final class SafetyCenterIssue implements Parcelable {
public Builder setConfirmationDialogDetails(
@Nullable ConfirmationDialogDetails confirmationDialogDetails) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mConfirmationDialogDetails = confirmationDialogDetails;
return this;
diff --git a/framework-s/java/android/safetycenter/SafetyCenterManager.java b/framework-s/java/android/safetycenter/SafetyCenterManager.java
index bb67f578f..35d09cce3 100644
--- a/framework-s/java/android/safetycenter/SafetyCenterManager.java
+++ b/framework-s/java/android/safetycenter/SafetyCenterManager.java
@@ -471,7 +471,7 @@ public final class SafetyCenterManager {
@RefreshReason int refreshReason, @NonNull List<String> safetySourceIds) {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException(
- "Method not supported for versions lower than UPSIDE_DOWN_CAKE");
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetySourceIds, "safetySourceIds cannot be null");
diff --git a/framework-s/java/android/safetycenter/SafetyEvent.java b/framework-s/java/android/safetycenter/SafetyEvent.java
index 72e8defaa..2a0d07032 100644
--- a/framework-s/java/android/safetycenter/SafetyEvent.java
+++ b/framework-s/java/android/safetycenter/SafetyEvent.java
@@ -240,7 +240,8 @@ public final class SafetyEvent implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetyEvent safetyEvent) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetyEvent);
mType = safetyEvent.mType;
diff --git a/framework-s/java/android/safetycenter/SafetySourceData.java b/framework-s/java/android/safetycenter/SafetySourceData.java
index 2e80621a2..04846dd75 100644
--- a/framework-s/java/android/safetycenter/SafetySourceData.java
+++ b/framework-s/java/android/safetycenter/SafetySourceData.java
@@ -216,7 +216,8 @@ public final class SafetySourceData implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Bundle getExtras() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mExtras;
}
@@ -274,7 +275,8 @@ public final class SafetySourceData implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetySourceData safetySourceData) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetySourceData);
mIssues.addAll(safetySourceData.mIssues);
@@ -299,13 +301,14 @@ public final class SafetySourceData implements Parcelable {
/**
* Sets additional information for the {@link SafetySourceData}.
*
- * If not set, the default value is {@link Bundle#EMPTY}.
+ * <p>If not set, the default value is {@link Bundle#EMPTY}.
*/
@NonNull
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setExtras(@NonNull Bundle extras) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mExtras = requireNonNull(extras);
return this;
@@ -319,7 +322,8 @@ public final class SafetySourceData implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder clearExtras() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mExtras = Bundle.EMPTY;
return this;
diff --git a/framework-s/java/android/safetycenter/SafetySourceIssue.java b/framework-s/java/android/safetycenter/SafetySourceIssue.java
index 985131764..de75aa298 100644
--- a/framework-s/java/android/safetycenter/SafetySourceIssue.java
+++ b/framework-s/java/android/safetycenter/SafetySourceIssue.java
@@ -337,7 +337,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public CharSequence getAttributionTitle() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mAttributionTitle;
}
@@ -418,7 +419,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Notification getCustomNotification() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mCustomNotification;
}
@@ -449,7 +451,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public int getNotificationBehavior() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mNotificationBehavior;
}
@@ -482,7 +485,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public String getDeduplicationId() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mDeduplicationId;
}
@@ -505,7 +509,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public int getIssueActionability() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mIssueActionability;
}
@@ -739,7 +744,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public ConfirmationDialogDetails getConfirmationDialogDetails() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mConfirmationDialogDetails;
}
@@ -938,7 +944,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull Action action) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(action);
mId = action.mId;
@@ -984,7 +991,8 @@ public final class SafetySourceIssue implements Parcelable {
public Builder setConfirmationDialogDetails(
@Nullable ConfirmationDialogDetails confirmationDialogDetails) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mConfirmationDialogDetails = confirmationDialogDetails;
return this;
@@ -1229,7 +1237,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetySourceIssue safetySourceIssue) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetySourceIssue);
mId = safetySourceIssue.mId;
@@ -1266,7 +1275,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public Builder setAttributionTitle(@Nullable CharSequence attributionTitle) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mAttributionTitle = attributionTitle;
return this;
@@ -1335,7 +1345,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setCustomNotification(@Nullable Notification customNotification) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mCustomNotification = customNotification;
return this;
@@ -1355,7 +1366,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setNotificationBehavior(@NotificationBehavior int notificationBehavior) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mNotificationBehavior = validateNotificationBehavior(notificationBehavior);
return this;
@@ -1370,7 +1382,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setDeduplicationId(@Nullable String deduplicationId) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mDeduplicationId = deduplicationId;
return this;
@@ -1388,7 +1401,8 @@ public final class SafetySourceIssue implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setIssueActionability(@IssueActionability int issueActionability) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mIssueActionability = validateIssueActionability(issueActionability);
return this;
diff --git a/framework-s/java/android/safetycenter/SafetySourceStatus.java b/framework-s/java/android/safetycenter/SafetySourceStatus.java
index 37095eb59..d8900f8d9 100644
--- a/framework-s/java/android/safetycenter/SafetySourceStatus.java
+++ b/framework-s/java/android/safetycenter/SafetySourceStatus.java
@@ -348,7 +348,8 @@ public final class SafetySourceStatus implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetySourceStatus safetySourceStatus) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetySourceStatus);
mTitle = safetySourceStatus.mTitle;
diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
index c94cedbd6..f6c6c2156 100644
--- a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
+++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java
@@ -122,7 +122,8 @@ public final class SafetyCenterConfig implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetyCenterConfig safetyCenterConfig) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetyCenterConfig);
mSafetySourcesGroups.addAll(safetyCenterConfig.mSafetySourcesGroups);
diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java
index fddb8b622..8aa897850 100644
--- a/framework-s/java/android/safetycenter/config/SafetySource.java
+++ b/framework-s/java/android/safetycenter/config/SafetySource.java
@@ -297,7 +297,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public String getOptionalPackageName() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mPackageName;
}
@@ -488,7 +489,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public boolean areNotificationsAllowed() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mNotificationsAllowed;
}
@@ -503,7 +505,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public String getDeduplicationGroup() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mDeduplicationGroup;
}
@@ -525,7 +528,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Set<String> getPackageCertificateHashes() {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
return mPackageCertificateHashes;
}
@@ -668,7 +672,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetySource safetySource) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(safetySource);
mType = safetySource.mType;
@@ -884,7 +889,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setNotificationsAllowed(boolean notificationsAllowed) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mNotificationsAllowed = notificationsAllowed;
return this;
@@ -903,7 +909,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder setDeduplicationGroup(@Nullable String deduplicationGroup) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mDeduplicationGroup = deduplicationGroup;
return this;
@@ -919,7 +926,8 @@ public final class SafetySource implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder addPackageCertificateHash(@NonNull String packageCertificateHash) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
mPackageCertificateHashes.add(packageCertificateHash);
return this;
diff --git a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
index 1bbe25bbb..9f9ff96cd 100644
--- a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
+++ b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java
@@ -314,7 +314,8 @@ public final class SafetySourcesGroup implements Parcelable {
@RequiresApi(UPSIDE_DOWN_CAKE)
public Builder(@NonNull SafetySourcesGroup original) {
if (!SdkLevel.isAtLeastU()) {
- throw new UnsupportedOperationException();
+ throw new UnsupportedOperationException(
+ "Method not supported on versions lower than UPSIDE_DOWN_CAKE");
}
requireNonNull(original);
mSafetySources.addAll(original.mSafetySources);
diff --git a/permissions/Android.bp b/permissions/Android.bp
index 8c7dab40b..6c1fdb8f8 100644
--- a/permissions/Android.bp
+++ b/permissions/Android.bp
@@ -19,9 +19,7 @@ package {
default_visibility: ["//packages/modules/Permission:__subpackages__"],
}
-prebuilt_etc {
+filegroup {
name: "privapp_allowlist_com.android.permissioncontroller.xml",
- sub_dir: "permissions",
- src: "com.android.permissioncontroller.xml",
- installable: false,
+ srcs: ["com.android.permissioncontroller.xml"],
}
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index 485be4e72..f18a9e79e 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -24,6 +24,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
+import android.app.admin.DevicePolicyManager;
import android.app.role.IOnRoleHoldersChangedListener;
import android.app.role.IRoleManager;
import android.app.role.RoleControllerManager;
@@ -33,6 +34,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -41,6 +44,8 @@ import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
@@ -55,6 +60,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.modules.utils.build.SdkLevel;
import com.android.permission.compat.UserHandleCompat;
import com.android.permission.util.ArrayUtils;
import com.android.permission.util.CollectionUtils;
@@ -181,13 +187,14 @@ public class RoleService extends SystemService implements RoleUserState.Callback
public void onStart() {
publishBinderService(Context.ROLE_SERVICE, new Stub());
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
- intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- intentFilter.addDataScheme("package");
- intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
+ Context context = getContext();
+ IntentFilter packageIntentFilter = new IntentFilter();
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ packageIntentFilter.addDataScheme("package");
+ packageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ context.registerReceiverForAllUsers(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int userId = UserHandleCompat.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
@@ -202,7 +209,44 @@ public class RoleService extends SystemService implements RoleUserState.Callback
}
maybeGrantDefaultRolesAsync(userId);
}
- }, intentFilter, null, null);
+ }, packageIntentFilter, null, null);
+
+ if (SdkLevel.isAtLeastV()) {
+ IntentFilter devicePolicyIntentFilter = new IntentFilter();
+ devicePolicyIntentFilter.addAction(
+ DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
+ devicePolicyIntentFilter.addAction(
+ DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED);
+ devicePolicyIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ context.registerReceiverForAllUsers(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int userId = getSendingUser().getIdentifier();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Device policy changed (" + intent.getAction()
+ + ") - re-running initial grants for user " + userId);
+ }
+ maybeGrantDefaultRolesAsync(userId);
+ }
+ }, devicePolicyIntentFilter, null, null);
+
+ context.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE), false,
+ new ContentObserver(ForegroundThread.getHandler()) {
+ public void onChange(boolean selfChange, Uri uri) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Settings.Global.DEVICE_DEMO_MODE changed.");
+ }
+ UserManager userManager =
+ context.getSystemService(UserManager.class);
+ List<UserHandle> users = userManager.getUserHandles(true);
+ int usersSize = users.size();
+ for (int i = 0; i < usersSize; i++) {
+ maybeGrantDefaultRolesAsync(users.get(i).getIdentifier());
+ }
+ }
+ });
+ }
}
@Override
diff --git a/service/java/com/android/role/TEST_MAPPING b/service/java/com/android/role/TEST_MAPPING
index 15173a9da..45cf62ff7 100644
--- a/service/java/com/android/role/TEST_MAPPING
+++ b/service/java/com/android/role/TEST_MAPPING
@@ -33,5 +33,32 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.StatsdAppSecurityAtomTest#testRoleHolder"
+ }
+ ]
+ },
+ {
+ "name": "CtsRoleTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
+ }
+ ]
+ }
]
}
diff --git a/service/java/com/android/safetycenter/ApiLock.java b/service/java/com/android/safetycenter/ApiLock.java
index 91466d3d5..f80e2ea32 100644
--- a/service/java/com/android/safetycenter/ApiLock.java
+++ b/service/java/com/android/safetycenter/ApiLock.java
@@ -16,10 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import androidx.annotation.RequiresApi;
-
/**
* A class that is used to strongly type the {@link Object} used to synchronize the Safety Center
* APIs.
@@ -29,7 +25,6 @@ import androidx.annotation.RequiresApi;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class ApiLock {
ApiLock() {}
}
diff --git a/service/java/com/android/safetycenter/DevicePolicyResources.java b/service/java/com/android/safetycenter/DevicePolicyResources.java
index 25cab343f..8d31c254b 100644
--- a/service/java/com/android/safetycenter/DevicePolicyResources.java
+++ b/service/java/com/android/safetycenter/DevicePolicyResources.java
@@ -16,8 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static java.util.Objects.requireNonNull;
import android.annotation.StringRes;
@@ -26,14 +24,11 @@ import android.app.admin.DevicePolicyResourcesManager;
import android.content.Context;
import android.os.Binder;
-import androidx.annotation.RequiresApi;
-
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.util.function.Supplier;
/** A class that handles dynamically updating enterprise-related resources. */
-@RequiresApi(TIRAMISU)
final class DevicePolicyResources {
private static final String SAFETY_CENTER_PREFIX = "SafetyCenter.";
@@ -46,31 +41,30 @@ final class DevicePolicyResources {
* DevicePolicyResourcesManager#getString}.
*/
static String getSafetySourceWorkString(
- SafetyCenterResourcesContext safetyCenterResourcesContext,
+ SafetyCenterResourcesApk safetyCenterResourcesApk,
String safetySourceId,
@StringRes int workResId) {
return getEnterpriseString(
- safetyCenterResourcesContext,
+ safetyCenterResourcesApk.getContext(),
safetySourceId,
- () -> safetyCenterResourcesContext.getString(workResId));
+ () -> safetyCenterResourcesApk.getString(workResId));
}
/**
* Returns the updated string for the {@code work_profile_paused} string by calling {@link
* DevicePolicyResourcesManager#getString}.
*/
- static String getWorkProfilePausedString(
- SafetyCenterResourcesContext safetyCenterResourcesContext) {
+ static String getWorkProfilePausedString(SafetyCenterResourcesApk safetyCenterResourcesApk) {
return getEnterpriseString(
- safetyCenterResourcesContext,
+ safetyCenterResourcesApk.getContext(),
WORK_PROFILE_PAUSED_TITLE,
- () -> safetyCenterResourcesContext.getStringByName("work_profile_paused"));
+ () -> safetyCenterResourcesApk.getStringByName("work_profile_paused"));
}
private static String getEnterpriseString(
Context context, String devicePolicyIdentifier, Supplier<String> defaultValueLoader) {
// This call requires the caller’s identity to match the package name of the given context.
- // However, the SafetyCenterResourcesContext’s has package name "android", which does not
+ // However, the SafetyCenterResourceApk Context's has package name "android", which does not
// necessarily match the caller’s package when making Binder calls, so the calling identity
// has to be cleared.
final long callingId = Binder.clearCallingIdentity();
diff --git a/service/java/com/android/safetycenter/PendingIntentFactory.java b/service/java/com/android/safetycenter/PendingIntentFactory.java
index 8c447c477..b52365c38 100644
--- a/service/java/com/android/safetycenter/PendingIntentFactory.java
+++ b/service/java/com/android/safetycenter/PendingIntentFactory.java
@@ -16,11 +16,8 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static java.util.Objects.requireNonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.content.Context;
@@ -32,9 +29,9 @@ import android.os.Binder;
import android.os.UserHandle;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.util.Arrays;
@@ -43,7 +40,6 @@ import java.util.Arrays;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class PendingIntentFactory {
private static final String TAG = "PendingIntentFactory";
@@ -53,12 +49,11 @@ public final class PendingIntentFactory {
private static final String IS_SETTINGS_HOMEPAGE = "is_from_settings_homepage";
private final Context mContext;
- private final SafetyCenterResourcesContext mSafetyCenterResourcesContext;
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
- PendingIntentFactory(
- Context context, SafetyCenterResourcesContext safetyCenterResourcesContext) {
+ PendingIntentFactory(Context context, SafetyCenterResourcesApk safetyCenterResourcesApk) {
mContext = context;
- mSafetyCenterResourcesContext = safetyCenterResourcesContext;
+ mSafetyCenterResourcesApk = safetyCenterResourcesApk;
}
/**
@@ -146,7 +141,7 @@ public final class PendingIntentFactory {
private boolean shouldAddSettingsHomepageExtra(String sourceId) {
return Arrays.asList(
- mSafetyCenterResourcesContext
+ mSafetyCenterResourcesApk
.getStringByName("config_useSettingsHomepageIntentExtra")
.split(","))
.contains(sourceId);
@@ -235,7 +230,8 @@ public final class PendingIntentFactory {
// This call requires the INTERACT_ACROSS_USERS permission.
final long callingId = Binder.clearCallingIdentity();
try {
- return context.createPackageContextAsUser(packageName, 0, UserHandle.of(userId));
+ return context.createPackageContextAsUser(
+ packageName, /* flags= */ 0, UserHandle.of(userId));
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Package name " + packageName + " not found", e);
return null;
diff --git a/service/java/com/android/safetycenter/RefreshReasons.java b/service/java/com/android/safetycenter/RefreshReasons.java
index ee318c7fd..f62d4cddb 100644
--- a/service/java/com/android/safetycenter/RefreshReasons.java
+++ b/service/java/com/android/safetycenter/RefreshReasons.java
@@ -16,7 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA;
import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA;
@@ -33,12 +32,7 @@ import android.safetycenter.SafetyCenterManager.RefreshReason;
import android.safetycenter.SafetyCenterManager.RefreshRequestType;
import android.util.Log;
-import androidx.annotation.RequiresApi;
-
-import com.android.modules.utils.build.SdkLevel;
-
/** Helpers to do with {@link RefreshReason}. */
-@RequiresApi(TIRAMISU)
final class RefreshReasons {
private static final String TAG = "RefreshReasons";
@@ -49,6 +43,7 @@ final class RefreshReasons {
* Validates the given {@link RefreshReason}, and throws an {@link IllegalArgumentException} in
* case of unexpected value.
*/
+ @TargetApi(UPSIDE_DOWN_CAKE)
static void validate(@RefreshReason int refreshReason) {
switch (refreshReason) {
case REFRESH_REASON_RESCAN_BUTTON_CLICK:
@@ -57,11 +52,9 @@ final class RefreshReasons {
case REFRESH_REASON_DEVICE_LOCALE_CHANGE:
case REFRESH_REASON_SAFETY_CENTER_ENABLED:
case REFRESH_REASON_OTHER:
+ case REFRESH_REASON_PERIODIC:
return;
}
- if (SdkLevel.isAtLeastU() && refreshReason == REFRESH_REASON_PERIODIC) {
- return;
- }
throw new IllegalArgumentException("Unexpected refresh reason: " + refreshReason);
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterBroadcastDispatcher.java b/service/java/com/android/safetycenter/SafetyCenterBroadcastDispatcher.java
index e8e6befe5..a36beb2d3 100644
--- a/service/java/com/android/safetycenter/SafetyCenterBroadcastDispatcher.java
+++ b/service/java/com/android/safetycenter/SafetyCenterBroadcastDispatcher.java
@@ -18,8 +18,8 @@ package com.android.safetycenter;
import static android.Manifest.permission.READ_SAFETY_CENTER_STATUS;
import static android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE;
+import static android.content.Intent.FLAG_INCLUDE_STOPPED_PACKAGES;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.os.PowerExemptionManager.REASON_REFRESH_SAFETY_SOURCES;
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES;
@@ -32,8 +32,6 @@ import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_SAFETY_CEN
import static java.util.Collections.unmodifiableList;
-import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
import android.app.BroadcastOptions;
import android.content.Context;
@@ -42,13 +40,12 @@ import android.os.Binder;
import android.os.UserHandle;
import android.safetycenter.SafetyCenterManager;
import android.safetycenter.SafetyCenterManager.RefreshReason;
-import android.safetycenter.SafetyCenterManager.RefreshRequestType;
import android.safetycenter.SafetySourceData;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.PackageUtils;
import com.android.safetycenter.SafetyCenterConfigReader.Broadcast;
@@ -67,7 +64,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterBroadcastDispatcher {
private static final String TAG = "SafetyCenterBroadcastDi";
@@ -139,7 +135,6 @@ final class SafetyCenterBroadcastDispatcher {
String broadcastId,
@Nullable List<String> requiredSourceIds) {
boolean hasSentAtLeastOneBroadcast = false;
- int requestType = RefreshReasons.toRefreshRequestType(refreshReason);
String packageName = broadcast.getPackageName();
Set<String> deniedSourceIds = getRefreshDeniedSourceIds(refreshReason);
SparseArray<List<String>> userIdsToSourceIds =
@@ -163,7 +158,7 @@ final class SafetyCenterBroadcastDispatcher {
continue;
}
- Intent intent = createRefreshIntent(requestType, packageName, sourceIds, broadcastId);
+ Intent intent = createRefreshIntent(refreshReason, packageName, sourceIds, broadcastId);
boolean broadcastWasSent =
sendBroadcastIfResolves(intent, UserHandle.of(userId), broadcastOptions);
if (broadcastWasSent) {
@@ -198,7 +193,11 @@ final class SafetyCenterBroadcastDispatcher {
}
Intent implicitIntent = createImplicitEnabledChangedIntent();
- sendBroadcast(implicitIntent, UserHandle.SYSTEM, READ_SAFETY_CENTER_STATUS, null);
+ sendBroadcast(
+ implicitIntent,
+ UserHandle.SYSTEM,
+ READ_SAFETY_CENTER_STATUS,
+ /* broadcastOptions= */ null);
}
private void sendEnabledChangedBroadcast(
@@ -206,15 +205,17 @@ final class SafetyCenterBroadcastDispatcher {
BroadcastOptions broadcastOptions,
List<UserProfileGroup> userProfileGroups) {
Intent intent = createExplicitEnabledChangedIntent(broadcast.getPackageName());
- // The same ENABLED reason is used here for both enable and disable events. It is not sent
- // externally and is only used internally to filter safety sources in the methods of the
- // Broadcast class.
- int refreshReason = REFRESH_REASON_SAFETY_CENTER_ENABLED;
for (int i = 0; i < userProfileGroups.size(); i++) {
UserProfileGroup userProfileGroup = userProfileGroups.get(i);
SparseArray<List<String>> userIdsToSourceIds =
- getUserIdsToSourceIds(broadcast, userProfileGroup, refreshReason);
+ getUserIdsToSourceIds(
+ broadcast,
+ userProfileGroup,
+ // The same ENABLED reason is used here for both enable and disable
+ // events. It is not sent externally and is only used internally to
+ // filter safety sources in the methods of the Broadcast class.
+ REFRESH_REASON_SAFETY_CENTER_ENABLED);
for (int j = 0; j < userIdsToSourceIds.size(); j++) {
int userId = userIdsToSourceIds.keyAt(j);
@@ -229,24 +230,22 @@ final class SafetyCenterBroadcastDispatcher {
if (!doesBroadcastResolve(intent, userHandle)) {
Log.w(
TAG,
- "No receiver for intent targeting "
+ "No receiver for intent targeting: "
+ intent.getPackage()
- + " and user "
- + userHandle);
+ + ", and user id: "
+ + userHandle.getIdentifier());
return false;
}
Log.v(
TAG,
- "Found receiver for intent targeting "
+ "Found receiver for intent targeting: "
+ intent.getPackage()
- + " and user "
- + userHandle);
+ + ", and user id: "
+ + userHandle.getIdentifier());
sendBroadcast(intent, userHandle, SEND_SAFETY_CENTER_UPDATE, broadcastOptions);
return true;
}
- // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
- @SuppressLint("NewApi")
private void sendBroadcast(
Intent intent,
UserHandle userHandle,
@@ -267,7 +266,7 @@ final class SafetyCenterBroadcastDispatcher {
private boolean doesBroadcastResolve(Intent broadcastIntent, UserHandle userHandle) {
return !PackageUtils.queryUnfilteredBroadcastReceiversAsUser(
- broadcastIntent, 0, userHandle.getIdentifier(), mContext)
+ broadcastIntent, /* flags= */ 0, userHandle.getIdentifier(), mContext)
.isEmpty();
}
@@ -280,24 +279,29 @@ final class SafetyCenterBroadcastDispatcher {
}
private static Intent createRefreshIntent(
- @RefreshRequestType int requestType,
+ @RefreshReason int refreshReason,
String packageName,
List<String> sourceIdsToRefresh,
String broadcastId) {
String[] sourceIdsArray = sourceIdsToRefresh.toArray(new String[0]);
- return createBroadcastIntent(ACTION_REFRESH_SAFETY_SOURCES)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE, requestType)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, sourceIdsArray)
- .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, broadcastId)
- .setPackage(packageName);
+ int requestType = RefreshReasons.toRefreshRequestType(refreshReason);
+ Intent refreshIntent =
+ createBroadcastIntent(ACTION_REFRESH_SAFETY_SOURCES)
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE, requestType)
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCE_IDS, sourceIdsArray)
+ .putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, broadcastId)
+ .setPackage(packageName);
+ boolean isUserInitiated = !RefreshReasons.isBackgroundRefresh(refreshReason);
+ if (isUserInitiated) {
+ return refreshIntent.addFlags(FLAG_INCLUDE_STOPPED_PACKAGES);
+ }
+ return refreshIntent;
}
private static Intent createBroadcastIntent(String intentAction) {
- return new Intent(intentAction).setFlags(FLAG_RECEIVER_FOREGROUND);
+ return new Intent(intentAction).addFlags(FLAG_RECEIVER_FOREGROUND);
}
- // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
- @SuppressLint("NewApi")
private static BroadcastOptions createBroadcastOptions() {
BroadcastOptions broadcastOptions = BroadcastOptions.makeBasic();
Duration allowListDuration = SafetyCenterFlags.getFgsAllowlistDuration();
diff --git a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
index 92959a47d..c473ad916 100644
--- a/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
+++ b/service/java/com/android/safetycenter/SafetyCenterConfigReader.java
@@ -16,12 +16,9 @@
package com.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.Nullable;
import android.content.res.Resources;
import android.safetycenter.config.SafetyCenterConfig;
import android.safetycenter.config.SafetySource;
@@ -29,11 +26,11 @@ import android.safetycenter.config.SafetySourcesGroup;
import android.util.ArrayMap;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.safetycenter.config.ParseException;
import com.android.safetycenter.config.SafetyCenterConfigParser;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -50,21 +47,20 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterConfigReader {
private static final String TAG = "SafetyCenterConfigReade";
- private final SafetyCenterResourcesContext mSafetyCenterResourcesContext;
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
@Nullable private SafetyCenterConfigInternal mConfigInternalFromXml;
@Nullable private SafetyCenterConfigInternal mConfigInternalOverrideForTests;
- /** Creates a {@link SafetyCenterConfigReader} from a {@link SafetyCenterResourcesContext}. */
- SafetyCenterConfigReader(SafetyCenterResourcesContext safetyCenterResourcesContext) {
- mSafetyCenterResourcesContext = safetyCenterResourcesContext;
+ /** Creates a {@link SafetyCenterConfigReader} from a {@link SafetyCenterResourcesApk}. */
+ SafetyCenterConfigReader(SafetyCenterResourcesApk safetyCenterResourcesApk) {
+ mSafetyCenterResourcesApk = safetyCenterResourcesApk;
}
/**
@@ -76,7 +72,7 @@ public final class SafetyCenterConfigReader {
* this method was {@code true}.
*/
boolean loadConfig() {
- SafetyCenterConfig safetyCenterConfig = readSafetyCenterConfig();
+ SafetyCenterConfig safetyCenterConfig = loadSafetyCenterConfig();
if (safetyCenterConfig == null) {
return false;
}
@@ -114,7 +110,7 @@ public final class SafetyCenterConfigReader {
/**
* Returns the groups of {@link SafetySource}, filtering out any sources where {@link
- * SafetySources#isLoggable(SafetySource)} is false (and any resultingly empty groups).
+ * SafetySources#isLoggable(SafetySource)} is {@code false} (and any resulting empty groups).
*/
public List<SafetySourcesGroup> getLoggableSafetySourcesGroups() {
return getCurrentConfigInternal().getLoggableSourcesGroups();
@@ -137,15 +133,15 @@ public final class SafetyCenterConfigReader {
@Nullable
public ExternalSafetySource getExternalSafetySource(
String safetySourceId, String callingPackageName) {
- SafetyCenterConfigInternal currentConfig = getCurrentConfigInternal();
+ SafetyCenterConfigInternal testConfig = mConfigInternalOverrideForTests;
SafetyCenterConfigInternal xmlConfig = requireNonNull(mConfigInternalFromXml);
- if (currentConfig == xmlConfig) {
+ if (testConfig == null) {
// No override, access source directly.
- return currentConfig.getExternalSafetySources().get(safetySourceId);
+ return xmlConfig.getExternalSafetySources().get(safetySourceId);
}
ExternalSafetySource externalSafetySourceInTestConfig =
- currentConfig.getExternalSafetySources().get(safetySourceId);
+ testConfig.getExternalSafetySources().get(safetySourceId);
ExternalSafetySource externalSafetySourceInRealConfig =
xmlConfig.getExternalSafetySources().get(safetySourceId);
@@ -179,16 +175,20 @@ public final class SafetyCenterConfigReader {
* source is expected to interact with Safety Center, but is currently being silenced / no-ops
* while an override for tests is in place.
*
- * <p>The {@code callingPackageName} is used to differentiate a real source being overridden. It
- * could be that a test is overriding a real source and as such the real source should not be
- * able to provide data while its override is in place.
+ * <p>The {@code callingPackageName} can be used to differentiate a real source being
+ * overridden. It could be that a test is overriding a real source and as such the real source
+ * should not be able to provide data while its override is in place.
*/
- public boolean isExternalSafetySourceActive(String safetySourceId, String callingPackageName) {
+ public boolean isExternalSafetySourceActive(
+ String safetySourceId, @Nullable String callingPackageName) {
ExternalSafetySource externalSafetySourceInCurrentConfig =
getCurrentConfigInternal().getExternalSafetySources().get(safetySourceId);
if (externalSafetySourceInCurrentConfig == null) {
return false;
}
+ if (callingPackageName == null) {
+ return true;
+ }
return Objects.equals(
externalSafetySourceInCurrentConfig.getSafetySource().getPackageName(),
callingPackageName);
@@ -225,26 +225,21 @@ public final class SafetyCenterConfigReader {
}
@Nullable
- private SafetyCenterConfig readSafetyCenterConfig() {
- InputStream in = mSafetyCenterResourcesContext.getSafetyCenterConfig();
+ private SafetyCenterConfig loadSafetyCenterConfig() {
+ InputStream in = mSafetyCenterResourcesApk.getSafetyCenterConfig();
if (in == null) {
- Log.e(TAG, "Cannot get safety center config file, safety center will be disabled.");
- return null;
- }
-
- Resources resources = mSafetyCenterResourcesContext.getResources();
- if (resources == null) {
- Log.e(TAG, "Cannot get safety center resources, safety center will be disabled.");
+ Log.e(TAG, "Cannot access Safety Center config file");
return null;
}
+ Resources resources = mSafetyCenterResourcesApk.getResources();
try {
SafetyCenterConfig safetyCenterConfig =
SafetyCenterConfigParser.parseXmlResource(in, resources);
- Log.i(TAG, "SafetyCenterConfig read successfully");
+ Log.d(TAG, "SafetyCenterConfig loaded successfully");
return safetyCenterConfig;
} catch (ParseException e) {
- Log.e(TAG, "Cannot read SafetyCenterConfig, safety center will be disabled.", e);
+ Log.e(TAG, "Cannot parse SafetyCenterConfig", e);
return null;
}
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataChangeNotifier.java b/service/java/com/android/safetycenter/SafetyCenterDataChangeNotifier.java
index e8bf2626a..0e5617c8d 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataChangeNotifier.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataChangeNotifier.java
@@ -16,12 +16,8 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.annotation.UserIdInt;
-import androidx.annotation.RequiresApi;
-
import com.android.safetycenter.notifications.SafetyCenterNotificationSender;
import java.util.List;
@@ -34,7 +30,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterDataChangeNotifier {
diff --git a/service/java/com/android/safetycenter/SafetyCenterDataFactory.java b/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
index fe4a1ee43..d74d160f4 100644
--- a/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
+++ b/service/java/com/android/safetycenter/SafetyCenterDataFactory.java
@@ -16,14 +16,14 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static com.android.safetycenter.internaldata.SafetyCenterBundles.ISSUES_TO_GROUPS_BUNDLE_KEY;
import static com.android.safetycenter.internaldata.SafetyCenterBundles.STATIC_ENTRIES_TO_IDS_BUNDLE_KEY;
import static java.util.Collections.emptyList;
-import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.content.Context;
@@ -50,7 +50,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.UserUtils;
@@ -61,7 +61,7 @@ import com.android.safetycenter.internaldata.SafetyCenterIds;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
import com.android.safetycenter.internaldata.SafetyCenterIssueId;
import com.android.safetycenter.internaldata.SafetyCenterIssueKey;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.util.ArrayList;
import java.util.List;
@@ -78,7 +78,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterDataFactory {
@@ -87,7 +86,7 @@ public final class SafetyCenterDataFactory {
private static final String ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID = "AndroidLockScreenSources";
private final Context mContext;
- private final SafetyCenterResourcesContext mSafetyCenterResourcesContext;
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
private final SafetyCenterConfigReader mSafetyCenterConfigReader;
private final SafetyCenterRefreshTracker mSafetyCenterRefreshTracker;
private final PendingIntentFactory mPendingIntentFactory;
@@ -96,13 +95,13 @@ public final class SafetyCenterDataFactory {
SafetyCenterDataFactory(
Context context,
- SafetyCenterResourcesContext safetyCenterResourcesContext,
+ SafetyCenterResourcesApk safetyCenterResourcesApk,
SafetyCenterConfigReader safetyCenterConfigReader,
SafetyCenterRefreshTracker safetyCenterRefreshTracker,
PendingIntentFactory pendingIntentFactory,
SafetyCenterDataManager safetyCenterDataManager) {
mContext = context;
- mSafetyCenterResourcesContext = safetyCenterResourcesContext;
+ mSafetyCenterResourcesApk = safetyCenterResourcesApk;
mSafetyCenterConfigReader = safetyCenterConfigReader;
mSafetyCenterRefreshTracker = safetyCenterRefreshTracker;
mPendingIntentFactory = pendingIntentFactory;
@@ -334,7 +333,7 @@ public final class SafetyCenterDataFactory {
if (SdkLevel.isAtLeastU()) {
CharSequence issueAttributionTitle =
TextUtils.isEmpty(safetySourceIssue.getAttributionTitle())
- ? mSafetyCenterResourcesContext.getOptionalString(
+ ? mSafetyCenterResourcesApk.getOptionalString(
safetySourcesGroup.getTitleResId())
: safetySourceIssue.getAttributionTitle();
safetyCenterIssueBuilder.setAttributionTitle(issueAttributionTitle);
@@ -400,8 +399,8 @@ public final class SafetyCenterDataFactory {
safetySource,
defaultPackageName,
userProfileGroup.getProfileParentUserId(),
- false,
- false));
+ /* isUserManaged= */ false,
+ /* isManagedUserRunning= */ false));
if (!SafetySources.supportsManagedProfiles(safetySource)) {
continue;
@@ -422,7 +421,7 @@ public final class SafetyCenterDataFactory {
safetySource,
defaultPackageName,
managedProfileUserId,
- true,
+ /* isUserManaged= */ true,
isManagedUserRunning));
}
}
@@ -443,7 +442,7 @@ public final class SafetyCenterDataFactory {
new SafetyCenterEntryOrGroup(
new SafetyCenterEntryGroup.Builder(
safetySourcesGroup.getId(),
- mSafetyCenterResourcesContext.getString(
+ mSafetyCenterResourcesApk.getString(
safetySourcesGroup.getTitleResId()))
.setSeverityLevel(groupSafetyCenterEntryLevel)
.setSummary(groupSummary)
@@ -509,13 +508,10 @@ public final class SafetyCenterDataFactory {
for (int i = 0; i < entries.size(); i++) {
SafetySourceKey key = toSafetySourceKey(entries.get(i).getId());
if (mSafetyCenterDataManager.sourceHasError(key)) {
- // We always use the singular form of the error string for groups because
- // they appear as single entries in the UI and this ensures consistency,
- // especially when subpages are enabled.
- return getRefreshErrorString(1);
+ return getRefreshErrorString();
}
}
- return mSafetyCenterResourcesContext.getStringByName("group_unknown_summary");
+ return mSafetyCenterResourcesApk.getStringByName("group_unknown_summary");
}
Log.w(
@@ -529,8 +525,7 @@ public final class SafetyCenterDataFactory {
private CharSequence getDefaultGroupSummary(
SafetySourcesGroup safetySourcesGroup, List<SafetyCenterEntry> entries) {
CharSequence groupSummary =
- mSafetyCenterResourcesContext.getOptionalString(
- safetySourcesGroup.getSummaryResId());
+ mSafetyCenterResourcesApk.getOptionalString(safetySourcesGroup.getSummaryResId());
if (safetySourcesGroup.getId().equals(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
&& TextUtils.isEmpty(groupSummary)) {
@@ -649,7 +644,7 @@ public final class SafetyCenterDataFactory {
.setSummary(
inQuietMode
? DevicePolicyResources.getWorkProfilePausedString(
- mSafetyCenterResourcesContext)
+ mSafetyCenterResourcesApk)
: safetySourceStatus.getSummary())
.setEnabled(enabled)
.setSeverityUnspecifiedIconType(severityUnspecifiedIconType)
@@ -710,20 +705,19 @@ public final class SafetyCenterDataFactory {
CharSequence title =
isUserManaged
? DevicePolicyResources.getSafetySourceWorkString(
- mSafetyCenterResourcesContext,
+ mSafetyCenterResourcesApk,
safetySource.getId(),
safetySource.getTitleForWorkResId())
- : mSafetyCenterResourcesContext.getString(safetySource.getTitleResId());
+ : mSafetyCenterResourcesApk.getString(safetySource.getTitleResId());
CharSequence summary =
mSafetyCenterDataManager.sourceHasError(
SafetySourceKey.of(safetySource.getId(), userId))
- ? getRefreshErrorString(1)
- : mSafetyCenterResourcesContext.getOptionalString(
+ ? getRefreshErrorString()
+ : mSafetyCenterResourcesApk.getOptionalString(
safetySource.getSummaryResId());
if (isQuietModeEnabled) {
enabled = false;
- summary =
- DevicePolicyResources.getWorkProfilePausedString(mSafetyCenterResourcesContext);
+ summary = DevicePolicyResources.getWorkProfilePausedString(mSafetyCenterResourcesApk);
}
return new SafetyCenterEntry.Builder(
SafetyCenterIds.encodeToString(safetyCenterEntryId), title)
@@ -754,8 +748,8 @@ public final class SafetyCenterDataFactory {
safetySource,
defaultPackageName,
userProfileGroup.getProfileParentUserId(),
- false,
- false);
+ /* isUserManaged= */ false,
+ /* isManagedUserRunning= */ false);
if (!SafetySources.supportsManagedProfiles(safetySource)) {
continue;
@@ -774,7 +768,7 @@ public final class SafetyCenterDataFactory {
safetySource,
defaultPackageName,
managedProfileUserId,
- true,
+ /* isUserManaged= */ true,
isManagedUserRunning);
}
}
@@ -785,7 +779,7 @@ public final class SafetyCenterDataFactory {
safetyCenterStaticEntryGroups.add(
new SafetyCenterStaticEntryGroup(
- mSafetyCenterResourcesContext.getString(safetySourcesGroup.getTitleResId()),
+ mSafetyCenterResourcesApk.getString(safetySourcesGroup.getTitleResId()),
staticEntries));
}
@@ -864,7 +858,7 @@ public final class SafetyCenterDataFactory {
.setSummary(
inQuietMode
? DevicePolicyResources.getWorkProfilePausedString(
- mSafetyCenterResourcesContext)
+ mSafetyCenterResourcesApk)
: safetySourceStatus.getSummary())
.setPendingIntent(entryPendingIntent)
.build();
@@ -914,19 +908,18 @@ public final class SafetyCenterDataFactory {
CharSequence title =
isUserManaged
? DevicePolicyResources.getSafetySourceWorkString(
- mSafetyCenterResourcesContext,
+ mSafetyCenterResourcesApk,
safetySource.getId(),
safetySource.getTitleForWorkResId())
- : mSafetyCenterResourcesContext.getString(safetySource.getTitleResId());
+ : mSafetyCenterResourcesApk.getString(safetySource.getTitleResId());
CharSequence summary =
mSafetyCenterDataManager.sourceHasError(
SafetySourceKey.of(safetySource.getId(), userId))
- ? getRefreshErrorString(1)
- : mSafetyCenterResourcesContext.getOptionalString(
+ ? getRefreshErrorString()
+ : mSafetyCenterResourcesApk.getOptionalString(
safetySource.getSummaryResId());
if (isQuietModeEnabled) {
- summary =
- DevicePolicyResources.getWorkProfilePausedString(mSafetyCenterResourcesContext);
+ summary = DevicePolicyResources.getWorkProfilePausedString(mSafetyCenterResourcesApk);
}
return new SafetyCenterStaticEntry.Builder(title)
.setSummary(summary)
@@ -1088,11 +1081,10 @@ public final class SafetyCenterDataFactory {
case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN:
case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK:
if (hasSettingsToReview) {
- return mSafetyCenterResourcesContext.getStringByName(
+ return mSafetyCenterResourcesApk.getStringByName(
"overall_severity_level_ok_review_title");
}
- return mSafetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_title");
+ return mSafetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title");
case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION:
return getStatusTitleFromIssueCategories(
topNonDismissedIssueInfo,
@@ -1117,6 +1109,7 @@ public final class SafetyCenterDataFactory {
return "";
}
+ @TargetApi(UPSIDE_DOWN_CAKE)
private String getStatusTitleFromIssueCategories(
@Nullable SafetySourceIssueInfo topNonDismissedIssueInfo,
String deviceResourceName,
@@ -1125,7 +1118,7 @@ public final class SafetyCenterDataFactory {
String dataResourceName,
String passwordsResourceName,
String personalSafetyResourceName) {
- String generalString = mSafetyCenterResourcesContext.getStringByName(generalResourceName);
+ String generalString = mSafetyCenterResourcesApk.getStringByName(generalResourceName);
if (topNonDismissedIssueInfo == null) {
Log.w(TAG, "No safety center issues found in a non-green status");
return generalString;
@@ -1133,22 +1126,17 @@ public final class SafetyCenterDataFactory {
int issueCategory = topNonDismissedIssueInfo.getSafetySourceIssue().getIssueCategory();
switch (issueCategory) {
case SafetySourceIssue.ISSUE_CATEGORY_DEVICE:
- return mSafetyCenterResourcesContext.getStringByName(deviceResourceName);
+ return mSafetyCenterResourcesApk.getStringByName(deviceResourceName);
case SafetySourceIssue.ISSUE_CATEGORY_ACCOUNT:
- return mSafetyCenterResourcesContext.getStringByName(accountResourceName);
+ return mSafetyCenterResourcesApk.getStringByName(accountResourceName);
case SafetySourceIssue.ISSUE_CATEGORY_GENERAL:
return generalString;
- }
- if (SdkLevel.isAtLeastU()) {
- switch (issueCategory) {
- case SafetySourceIssue.ISSUE_CATEGORY_DATA:
- return mSafetyCenterResourcesContext.getStringByName(dataResourceName);
- case SafetySourceIssue.ISSUE_CATEGORY_PASSWORDS:
- return mSafetyCenterResourcesContext.getStringByName(passwordsResourceName);
- case SafetySourceIssue.ISSUE_CATEGORY_PERSONAL_SAFETY:
- return mSafetyCenterResourcesContext.getStringByName(
- personalSafetyResourceName);
- }
+ case SafetySourceIssue.ISSUE_CATEGORY_DATA:
+ return mSafetyCenterResourcesApk.getStringByName(dataResourceName);
+ case SafetySourceIssue.ISSUE_CATEGORY_PASSWORDS:
+ return mSafetyCenterResourcesApk.getStringByName(passwordsResourceName);
+ case SafetySourceIssue.ISSUE_CATEGORY_PERSONAL_SAFETY:
+ return mSafetyCenterResourcesApk.getStringByName(personalSafetyResourceName);
}
Log.w(TAG, "Unexpected SafetySourceIssue.IssueCategory: " + issueCategory);
@@ -1172,17 +1160,16 @@ public final class SafetyCenterDataFactory {
case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK:
if (topNonDismissedIssue == null) {
if (safetyCenterOverallState.hasSettingsToReview()) {
- return mSafetyCenterResourcesContext.getStringByName(
+ return mSafetyCenterResourcesApk.getStringByName(
"overall_severity_level_ok_review_summary");
}
- return mSafetyCenterResourcesContext.getStringByName(
+ return mSafetyCenterResourcesApk.getStringByName(
"overall_severity_level_ok_summary");
} else if (isTip(topNonDismissedIssue.getSafetySourceIssue())) {
- return mSafetyCenterResourcesContext.getStringByName(
- "overall_severity_level_tip_summary", numTipIssues);
+ return getIcuPluralsString("overall_severity_level_tip_summary", numTipIssues);
} else if (isAutomatic(topNonDismissedIssue.getSafetySourceIssue())) {
- return mSafetyCenterResourcesContext.getStringByName(
+ return getIcuPluralsString(
"overall_severity_level_action_taken_summary", numAutomaticIssues);
}
// Fall through.
@@ -1207,14 +1194,14 @@ public final class SafetyCenterDataFactory {
== SafetySourceIssue.ISSUE_ACTIONABILITY_AUTOMATIC;
}
- private String getRefreshErrorString(int numberOfErrorEntries) {
- return getIcuPluralsString("refresh_error", numberOfErrorEntries);
+ private String getRefreshErrorString() {
+ return getIcuPluralsString("refresh_error", /* count= */ 1);
}
private String getIcuPluralsString(String name, int count, Object... formatArgs) {
MessageFormat messageFormat =
new MessageFormat(
- mSafetyCenterResourcesContext.getStringByName(name, formatArgs),
+ mSafetyCenterResourcesApk.getStringByName(name, formatArgs),
Locale.getDefault());
ArrayMap<String, Object> arguments = new ArrayMap<>();
arguments.put("count", count);
@@ -1233,7 +1220,7 @@ public final class SafetyCenterDataFactory {
}
// Fall through.
case SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS:
- return mSafetyCenterResourcesContext.getStringByName("scanning_title");
+ return mSafetyCenterResourcesApk.getStringByName("scanning_title");
}
Log.w(TAG, "Unexpected SafetyCenterStatus.RefreshStatus: " + refreshStatus);
@@ -1248,7 +1235,7 @@ public final class SafetyCenterDataFactory {
return null;
case SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS:
case SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS:
- return mSafetyCenterResourcesContext.getStringByName("loading_summary");
+ return mSafetyCenterResourcesApk.getStringByName("loading_summary");
}
Log.w(TAG, "Unexpected SafetyCenterStatus.RefreshStatus: " + refreshStatus);
diff --git a/service/java/com/android/safetycenter/SafetyCenterFlags.java b/service/java/com/android/safetycenter/SafetyCenterFlags.java
index 1fc88d4b0..821987ce9 100644
--- a/service/java/com/android/safetycenter/SafetyCenterFlags.java
+++ b/service/java/com/android/safetycenter/SafetyCenterFlags.java
@@ -16,10 +16,8 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyCenterManager.RefreshReason;
-import android.annotation.Nullable;
import android.os.Binder;
import android.provider.DeviceConfig;
import android.safetycenter.SafetySourceData;
@@ -27,10 +25,10 @@ import android.safetycenter.SafetySourceIssue;
import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.io.PrintWriter;
import java.time.Duration;
@@ -40,7 +38,6 @@ import java.time.Duration;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetyCenterFlags {
private static final String TAG = "SafetyCenterFlags";
@@ -63,9 +60,6 @@ public final class SafetyCenterFlags {
private static final String PROPERTY_NOTIFICATION_RESURFACE_INTERVAL =
"safety_center_notification_resurface_interval";
- private static final String PROPERTY_SHOW_ERROR_ENTRIES_ON_TIMEOUT =
- "safety_center_show_error_entries_on_timeout";
-
private static final String PROPERTY_REPLACE_LOCK_SCREEN_ICON_ACTION =
"safety_center_replace_lock_screen_icon_action";
@@ -131,27 +125,29 @@ public final class SafetyCenterFlags {
private static volatile String sIssueCategoryAllowlistDefault = "";
- private static volatile String sRefreshOnPageOpenSourcesDefault =
- "AndroidBiometrics,AndroidLockScreen";
+ private static volatile String sRefreshOnPageOpenSourcesDefault = "AndroidBiometrics";
- static void init(SafetyCenterResourcesContext resourceContext) {
+ static void init(SafetyCenterResourcesApk safetyCenterResourcesApk) {
String untrackedSourcesDefault =
- resourceContext.getOptionalStringByName("config_defaultUntrackedSources");
+ safetyCenterResourcesApk.getOptionalStringByName("config_defaultUntrackedSources");
if (untrackedSourcesDefault != null) {
sUntrackedSourcesDefault = untrackedSourcesDefault;
}
String backgroundRefreshDenyDefault =
- resourceContext.getOptionalStringByName("config_defaultBackgroundRefreshDeny");
+ safetyCenterResourcesApk.getOptionalStringByName(
+ "config_defaultBackgroundRefreshDeny");
if (backgroundRefreshDenyDefault != null) {
sBackgroundRefreshDenyDefault = backgroundRefreshDenyDefault;
}
String issueCategoryAllowlistDefault =
- resourceContext.getOptionalStringByName("config_defaultIssueCategoryAllowlist");
+ safetyCenterResourcesApk.getOptionalStringByName(
+ "config_defaultIssueCategoryAllowlist");
if (issueCategoryAllowlistDefault != null) {
sIssueCategoryAllowlistDefault = issueCategoryAllowlistDefault;
}
String refreshOnPageOpenSourcesDefault =
- resourceContext.getOptionalStringByName("config_defaultRefreshOnPageOpenSources");
+ safetyCenterResourcesApk.getOptionalStringByName(
+ "config_defaultRefreshOnPageOpenSources");
if (refreshOnPageOpenSourcesDefault != null) {
sRefreshOnPageOpenSourcesDefault = refreshOnPageOpenSourcesDefault;
}
@@ -173,7 +169,6 @@ public final class SafetyCenterFlags {
getImmediateNotificationBehaviorIssues());
printFlag(
fout, PROPERTY_NOTIFICATION_RESURFACE_INTERVAL, getNotificationResurfaceInterval());
- printFlag(fout, PROPERTY_SHOW_ERROR_ENTRIES_ON_TIMEOUT, getShowErrorEntriesOnTimeout());
printFlag(fout, PROPERTY_REPLACE_LOCK_SCREEN_ICON_ACTION, getReplaceLockScreenIconAction());
printFlag(fout, PROPERTY_RESOLVING_ACTION_TIMEOUT_MILLIS, getResolvingActionTimeout());
printFlag(fout, PROPERTY_FGS_ALLOWLIST_DURATION_MILLIS, getFgsAllowlistDuration());
@@ -284,13 +279,6 @@ public final class SafetyCenterFlags {
}
/**
- * Returns whether we should show error entries for sources that timeout when refreshing them.
- */
- static boolean getShowErrorEntriesOnTimeout() {
- return getBoolean(PROPERTY_SHOW_ERROR_ENTRIES_ON_TIMEOUT, true);
- }
-
- /**
* Returns whether we should replace the lock screen source's {@link
* android.safetycenter.SafetySourceStatus.IconAction}.
*/
@@ -442,7 +430,7 @@ public final class SafetyCenterFlags {
if (allowlistedCertString == null) {
return new ArraySet<>();
}
- return new ArraySet<String>(allowlistedCertString.split("\\|"));
+ return new ArraySet<>(allowlistedCertString.split("\\|"));
}
/**
diff --git a/service/java/com/android/safetycenter/SafetyCenterListeners.java b/service/java/com/android/safetycenter/SafetyCenterListeners.java
index 9e07c3d17..5f89f46ff 100644
--- a/service/java/com/android/safetycenter/SafetyCenterListeners.java
+++ b/service/java/com/android/safetycenter/SafetyCenterListeners.java
@@ -16,9 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.IBinder;
import android.os.RemoteCallbackList;
@@ -30,7 +27,7 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicReference;
@@ -43,7 +40,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterListeners {
@@ -67,7 +63,7 @@ final class SafetyCenterListeners {
try {
listener.onSafetyCenterDataChanged(safetyCenterData);
} catch (RemoteException e) {
- Log.e(TAG, "Error delivering SafetyCenterData to listener", e);
+ Log.w(TAG, "Error delivering SafetyCenterData to listener", e);
}
}
@@ -81,7 +77,7 @@ final class SafetyCenterListeners {
try {
listener.onError(safetyCenterErrorDetails);
} catch (RemoteException e) {
- Log.e(TAG, "Error delivering SafetyCenterErrorDetails to listener", e);
+ Log.w(TAG, "Error delivering SafetyCenterErrorDetails to listener", e);
}
}
@@ -94,7 +90,11 @@ final class SafetyCenterListeners {
int[] relevantUserIds = userProfileGroup.getProfileParentAndManagedRunningProfilesUserIds();
for (int i = 0; i < relevantUserIds.length; i++) {
deliverUpdateForUser(
- relevantUserIds[i], userProfileGroup, safetyCenterDataCache, true, null);
+ relevantUserIds[i],
+ userProfileGroup,
+ safetyCenterDataCache,
+ /* updateSafetyCenterData= */ true,
+ /* safetyCenterErrorDetails= */ null);
}
}
@@ -111,7 +111,7 @@ final class SafetyCenterListeners {
relevantUserIds[i],
userProfileGroup,
safetyCenterDataCache,
- false,
+ /* updateSafetyCenterData= */ false,
safetyCenterErrorDetails);
}
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java b/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
index a28ce7d22..d98127300 100644
--- a/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
+++ b/service/java/com/android/safetycenter/SafetyCenterRefreshTracker.java
@@ -16,14 +16,12 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_RESCAN_BUTTON_CLICK;
import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__TIMEOUT;
import static com.android.safetycenter.logging.SafetyCenterStatsdLogger.toSystemEventResult;
import android.annotation.ElapsedRealtimeLong;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.SystemClock;
@@ -34,7 +32,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.UserUtils;
import com.android.safetycenter.logging.SafetyCenterStatsdLogger;
@@ -53,7 +51,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterRefreshTracker {
private static final String TAG = "SafetyCenterRefreshTrac";
@@ -78,15 +75,15 @@ public final class SafetyCenterRefreshTracker {
String reportRefreshInProgress(
@RefreshReason int refreshReason, UserProfileGroup userProfileGroup) {
if (mRefreshInProgress != null) {
- Log.w(TAG, "Replacing an ongoing refresh");
+ Log.i(TAG, "Replacing ongoing refresh with id: " + mRefreshInProgress.getId());
}
String refreshBroadcastId = UUID.randomUUID() + "_" + mRefreshCounter++;
- Log.v(
+ Log.d(
TAG,
- "Starting a new refresh with refreshReason:"
+ "Starting a new refresh with reason: "
+ refreshReason
- + " refreshBroadcastId:"
+ + ", and id: "
+ refreshBroadcastId);
mRefreshInProgress =
@@ -158,8 +155,7 @@ public final class SafetyCenterRefreshTracker {
*/
public boolean reportSourceRefreshCompleted(
String refreshBroadcastId,
- String sourceId,
- @UserIdInt int userId,
+ SafetySourceKey safetySourceKey,
boolean successful,
boolean dataChanged) {
RefreshInProgress refreshInProgress =
@@ -168,9 +164,9 @@ public final class SafetyCenterRefreshTracker {
return false;
}
- SafetySourceKey sourceKey = SafetySourceKey.of(sourceId, userId);
Duration duration =
- refreshInProgress.markSourceRefreshComplete(sourceKey, successful, dataChanged);
+ refreshInProgress.markSourceRefreshComplete(
+ safetySourceKey, successful, dataChanged);
int refreshReason = refreshInProgress.getReason();
int requestType = RefreshReasons.toRefreshRequestType(refreshReason);
@@ -178,8 +174,8 @@ public final class SafetyCenterRefreshTracker {
int sourceResult = toSystemEventResult(successful);
SafetyCenterStatsdLogger.writeSourceRefreshSystemEvent(
requestType,
- sourceId,
- UserUtils.isManagedProfile(userId, mContext),
+ safetySourceKey.getSourceId(),
+ UserUtils.isManagedProfile(safetySourceKey.getUserId(), mContext),
duration,
sourceResult,
refreshReason,
@@ -237,7 +233,7 @@ public final class SafetyCenterRefreshTracker {
*/
void clearRefreshForUser(@UserIdInt int userId) {
if (mRefreshInProgress == null) {
- Log.v(TAG, "Clear refresh for user called but no refresh in progress");
+ Log.d(TAG, "Clear refresh for user called but no refresh in progress");
return;
}
if (mRefreshInProgress.clearForUser(userId)) {
@@ -272,6 +268,15 @@ public final class SafetyCenterRefreshTracker {
int refreshReason = clearedRefresh.getReason();
int requestType = RefreshReasons.toRefreshRequestType(refreshReason);
+ Log.w(
+ TAG,
+ "Timeout after "
+ + clearedRefresh.getDurationSinceStart()
+ + " for refresh with reason: "
+ + refreshReason
+ + ", and id: "
+ + clearedRefresh.getId());
+
for (int i = 0; i < timedOutSources.size(); i++) {
SafetySourceKey sourceKey = timedOutSources.valueAt(i);
Duration duration = clearedRefresh.getDurationSinceSourceStart(sourceKey);
@@ -285,6 +290,15 @@ public final class SafetyCenterRefreshTracker {
refreshReason,
false);
}
+
+ Log.w(
+ TAG,
+ "Refresh with id: "
+ + clearedRefresh.getId()
+ + " timed out for tracked source id: "
+ + sourceKey.getSourceId()
+ + ", and user id: "
+ + sourceKey.getUserId());
}
SafetyCenterStatsdLogger.writeWholeRefreshSystemEvent(
@@ -298,7 +312,7 @@ public final class SafetyCenterRefreshTracker {
}
/**
- * Clears the any refresh in progress and returns it for the caller to do what it needs to.
+ * Clears the refresh in progress and returns it for the caller to do what it needs to.
*
* <p>If there was no refresh in progress then {@code null} is returned.
*/
@@ -306,11 +320,11 @@ public final class SafetyCenterRefreshTracker {
private RefreshInProgress clearRefreshInternal() {
RefreshInProgress refreshToClear = mRefreshInProgress;
if (refreshToClear == null) {
- Log.v(TAG, "Clear refresh called but no refresh in progress");
+ Log.d(TAG, "Clear refresh called but no refresh in progress");
return null;
}
- Log.v(TAG, "Clearing refresh with refreshBroadcastId:" + refreshToClear.getId());
+ Log.v(TAG, "Clearing refresh with id: " + refreshToClear.getId());
mRefreshInProgress = null;
return refreshToClear;
}
@@ -324,13 +338,7 @@ public final class SafetyCenterRefreshTracker {
String methodName, String refreshBroadcastId) {
RefreshInProgress refreshInProgress = mRefreshInProgress;
if (refreshInProgress == null || !refreshInProgress.getId().equals(refreshBroadcastId)) {
- Log.i(
- TAG,
- methodName
- + " called for invalid refresh broadcast id: "
- + refreshBroadcastId
- + "; no such refresh in"
- + " progress");
+ Log.i(TAG, methodName + " called with invalid refresh id: " + refreshBroadcastId);
return null;
}
return refreshInProgress;
@@ -435,19 +443,19 @@ public final class SafetyCenterRefreshTracker {
}
Log.v(
TAG,
- "Refresh started for sourceId:"
+ "Refresh with id: "
+ + mId
+ + " started for source id: "
+ safetySourceKey.getSourceId()
- + " userId:"
+ + ", user id: "
+ safetySourceKey.getUserId()
- + " with refreshBroadcastId:"
- + mId
- + " at currentElapsedMillis:"
+ + ", elapsed millis: "
+ currentElapsedMillis
- + " & tracking:"
+ + ", tracking: "
+ tracked
+ ", now "
+ mSourceRefreshesInFlight.size()
- + " tracked sources in flight.");
+ + " tracked sources in flight");
}
@Nullable
@@ -464,23 +472,23 @@ public final class SafetyCenterRefreshTracker {
: Duration.ofMillis(SystemClock.elapsedRealtime() - startElapsedMillis);
Log.v(
TAG,
- "Refresh completed for sourceId:"
+ "Refresh with id: "
+ + mId
+ + " completed for source id: "
+ safetySourceKey.getSourceId()
- + " userId:"
+ + ", user id: "
+ safetySourceKey.getUserId()
- + " with refreshBroadcastId:"
- + mId
- + " duration:"
+ + ", duration: "
+ duration
- + " successful:"
+ + ", successful: "
+ successful
- + " dataChanged:"
+ + ", data changed: "
+ dataChanged
- + " & tracking:"
+ + ", tracking: "
+ tracked
- + ", "
+ + ", now "
+ mSourceRefreshesInFlight.size()
- + " tracked sources still in flight.");
+ + " tracked sources in flight");
return duration;
}
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index f23f041bd..98e97a26c 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -21,8 +21,8 @@ import static android.Manifest.permission.READ_SAFETY_CENTER_STATUS;
import static android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_DEVICE_LOCALE_CHANGE;
import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_OTHER;
import static android.safetycenter.SafetyCenterManager.RefreshReason;
import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED;
@@ -35,11 +35,10 @@ import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriend
import static java.util.Objects.requireNonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.StatsManager;
-import android.app.StatsManager.StatsPullAtomCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -69,13 +68,17 @@ import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.Keep;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.android.internal.annotations.GuardedBy;
import com.android.modules.utils.BackgroundThread;
+import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.ForegroundThread;
import com.android.permission.util.UserUtils;
+import com.android.safetycenter.data.AndroidLockScreenFix;
import com.android.safetycenter.data.SafetyCenterDataManager;
+import com.android.safetycenter.data.SafetyEventFix;
import com.android.safetycenter.internaldata.SafetyCenterIds;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
import com.android.safetycenter.internaldata.SafetyCenterIssueId;
@@ -85,16 +88,13 @@ import com.android.safetycenter.notifications.SafetyCenterNotificationChannels;
import com.android.safetycenter.notifications.SafetyCenterNotificationReceiver;
import com.android.safetycenter.notifications.SafetyCenterNotificationSender;
import com.android.safetycenter.pendingintents.PendingIntentSender;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
-import java.util.concurrent.Executor;
-
-import javax.annotation.concurrent.NotThreadSafe;
/**
* Service for the safety center.
@@ -102,7 +102,6 @@ import javax.annotation.concurrent.NotThreadSafe;
* @hide
*/
@Keep
-@RequiresApi(TIRAMISU)
public final class SafetyCenterService extends SystemService {
private static final String TAG = "SafetyCenterService";
@@ -112,9 +111,8 @@ public final class SafetyCenterService extends SystemService {
@GuardedBy("mApiLock")
private final SafetyCenterTimeouts mSafetyCenterTimeouts = new SafetyCenterTimeouts();
- private final SafetyCenterResourcesContext mSafetyCenterResourcesContext;
-
- private final SafetyCenterNotificationChannels mNotificationChannels;
+ @GuardedBy("mApiLock")
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
@GuardedBy("mApiLock")
private final SafetyCenterConfigReader mSafetyCenterConfigReader;
@@ -132,6 +130,9 @@ public final class SafetyCenterService extends SystemService {
private final SafetyCenterListeners mSafetyCenterListeners;
@GuardedBy("mApiLock")
+ private final SafetyCenterNotificationChannels mNotificationChannels;
+
+ @GuardedBy("mApiLock")
private final SafetyCenterNotificationSender mNotificationSender;
@GuardedBy("mApiLock")
@@ -140,16 +141,15 @@ public final class SafetyCenterService extends SystemService {
@GuardedBy("mApiLock")
private final SafetyCenterDataChangeNotifier mSafetyCenterDataChangeNotifier;
- private final StatsPullAtomCallback mPullAtomCallback;
private final boolean mDeviceSupportsSafetyCenter;
/** Whether the {@link SafetyCenterConfig} was successfully loaded. */
- private volatile boolean mConfigAvailable;
+ private volatile boolean mConfigAvailable = false;
public SafetyCenterService(Context context) {
super(context);
- mSafetyCenterResourcesContext = new SafetyCenterResourcesContext(context);
- mSafetyCenterConfigReader = new SafetyCenterConfigReader(mSafetyCenterResourcesContext);
+ mSafetyCenterResourcesApk = new SafetyCenterResourcesApk(context);
+ mSafetyCenterConfigReader = new SafetyCenterConfigReader(mSafetyCenterResourcesApk);
mSafetyCenterRefreshTracker = new SafetyCenterRefreshTracker(context);
mSafetyCenterDataManager =
new SafetyCenterDataManager(
@@ -157,17 +157,17 @@ public final class SafetyCenterService extends SystemService {
mSafetyCenterDataFactory =
new SafetyCenterDataFactory(
context,
- mSafetyCenterResourcesContext,
+ mSafetyCenterResourcesApk,
mSafetyCenterConfigReader,
mSafetyCenterRefreshTracker,
- new PendingIntentFactory(context, mSafetyCenterResourcesContext),
+ new PendingIntentFactory(context, mSafetyCenterResourcesApk),
mSafetyCenterDataManager);
mSafetyCenterListeners = new SafetyCenterListeners(mSafetyCenterDataFactory);
- mNotificationChannels = new SafetyCenterNotificationChannels(mSafetyCenterResourcesContext);
+ mNotificationChannels = new SafetyCenterNotificationChannels(mSafetyCenterResourcesApk);
mNotificationSender =
SafetyCenterNotificationSender.newInstance(
context,
- mSafetyCenterResourcesContext,
+ mSafetyCenterResourcesApk,
mNotificationChannels,
mSafetyCenterDataManager);
mSafetyCenterBroadcastDispatcher =
@@ -176,13 +176,6 @@ public final class SafetyCenterService extends SystemService {
mSafetyCenterConfigReader,
mSafetyCenterRefreshTracker,
mSafetyCenterDataManager);
- mPullAtomCallback =
- new SafetyCenterPullAtomCallback(
- context,
- mApiLock,
- mSafetyCenterConfigReader,
- mSafetyCenterDataFactory,
- mSafetyCenterDataManager);
mSafetyCenterDataChangeNotifier =
new SafetyCenterDataChangeNotifier(mNotificationSender, mSafetyCenterListeners);
mDeviceSupportsSafetyCenter =
@@ -191,57 +184,98 @@ public final class SafetyCenterService extends SystemService {
Resources.getSystem()
.getIdentifier(
"config_enableSafetyCenter", "bool", "android"));
- if (!mDeviceSupportsSafetyCenter) {
- Log.i(TAG, "Device does not support safety center, safety center will be disabled.");
- }
}
@Override
public void onStart() {
publishBinderService(Context.SAFETY_CENTER_SERVICE, new Stub());
- if (mDeviceSupportsSafetyCenter) {
- synchronized (mApiLock) {
- mSafetyCenterResourcesContext.init();
- SafetyCenterFlags.init(mSafetyCenterResourcesContext);
- mConfigAvailable = mSafetyCenterConfigReader.loadConfig();
- if (mConfigAvailable) {
- mSafetyCenterDataManager.loadPersistableDataStateFromFile();
- new UserBroadcastReceiver().register(getContext());
- new SafetyCenterNotificationReceiver(
- this,
- mSafetyCenterDataManager,
- mSafetyCenterDataChangeNotifier,
- mApiLock)
- .register(getContext());
- new LocaleBroadcastReceiver().register(getContext());
- }
+ if (!mDeviceSupportsSafetyCenter) {
+ Log.i(TAG, "Device does not support Safety Center, it will be disabled");
+ return;
+ }
+
+ synchronized (mApiLock) {
+ boolean safetyCenterResourcesInitialized = mSafetyCenterResourcesApk.init();
+ if (!safetyCenterResourcesInitialized) {
+ Log.e(TAG, "Cannot init Safety Center resources, Safety Center will be disabled");
+ return;
}
+
+ SafetyCenterFlags.init(mSafetyCenterResourcesApk);
+
+ if (!mSafetyCenterConfigReader.loadConfig()) {
+ Log.e(TAG, "Cannot init Safety Center config, Safety Center will be disabled");
+ return;
+ }
+
+ mConfigAvailable = true;
+ mSafetyCenterDataManager.loadPersistableDataStateFromFile();
+ new UserBroadcastReceiver().register(getContext());
+ new SafetyCenterNotificationReceiver(
+ /* service= */ this,
+ mSafetyCenterDataManager,
+ mSafetyCenterDataChangeNotifier,
+ mApiLock)
+ .register(getContext());
+ new LocaleBroadcastReceiver().register(getContext());
}
}
@Override
public void onBootPhase(int phase) {
- if (phase == SystemService.PHASE_BOOT_COMPLETED && canUseSafetyCenter()) {
- registerSafetyCenterEnabledListener();
- registerSafetyCenterPullAtomCallback();
- mNotificationChannels.createAllChannelsForAllUsers(getContext());
+ if (phase != SystemService.PHASE_BOOT_COMPLETED || !canUseSafetyCenter()) {
+ return;
+ }
+
+ SafetyCenterPullAtomCallback pullAtomCallback;
+ synchronized (mApiLock) {
+ registerSafetyCenterEnabledListenerLocked();
+ pullAtomCallback = newSafetyCenterPullAtomCallbackLocked();
}
+ registerSafetyCenterPullAtomCallback(pullAtomCallback);
}
- private void registerSafetyCenterEnabledListener() {
- Executor foregroundThreadExecutor = ForegroundThread.getExecutor();
- SafetyCenterEnabledListener listener = new SafetyCenterEnabledListener();
- // Ensure the listener is called first with the current state on the same thread.
- foregroundThreadExecutor.execute(listener::setInitialState);
+ @GuardedBy("mApiLock")
+ private void registerSafetyCenterEnabledListenerLocked() {
+ SafetyCenterEnabledListener safetyCenterEnabledListener = new SafetyCenterEnabledListener();
DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_PRIVACY, foregroundThreadExecutor, listener);
+ DeviceConfig.NAMESPACE_PRIVACY,
+ ForegroundThread.getExecutor(),
+ safetyCenterEnabledListener);
+ // Set the initial state *after* registering the listener, in the unlikely event that the
+ // flag changes between creating the listener and registering it (in which case we could
+ // miss an update and end up with an inconsistent state).
+ setInitialStateLocked(safetyCenterEnabledListener);
+ }
+
+ @GuardedBy("mApiLock")
+ @SuppressWarnings("GuardedBy")
+ // @GuardedBy is unable to infer that the `SafetyCenterService.this.mApiLock` in
+ // `SafetyCenterService` is the same as the one in `SafetyCenterEnabledListener` here, so it
+ // has to be suppressed.
+ private void setInitialStateLocked(SafetyCenterEnabledListener safetyCenterEnabledListener) {
+ safetyCenterEnabledListener.setInitialStateLocked();
+ }
+
+ @GuardedBy("mApiLock")
+ private SafetyCenterPullAtomCallback newSafetyCenterPullAtomCallbackLocked() {
+ return new SafetyCenterPullAtomCallback(
+ getContext(),
+ mApiLock,
+ mSafetyCenterConfigReader,
+ mSafetyCenterDataFactory,
+ mSafetyCenterDataManager);
}
- private void registerSafetyCenterPullAtomCallback() {
+ private void registerSafetyCenterPullAtomCallback(
+ SafetyCenterPullAtomCallback pullAtomCallback) {
StatsManager statsManager =
requireNonNull(getContext().getSystemService(StatsManager.class));
statsManager.setPullAtomCallback(
- SAFETY_STATE, null, BackgroundThread.getExecutor(), mPullAtomCallback);
+ SAFETY_STATE,
+ /* metadata= */ null,
+ BackgroundThread.getExecutor(),
+ pullAtomCallback);
}
/** Service implementation of {@link ISafetyCenterManager.Stub}. */
@@ -275,6 +309,16 @@ public final class SafetyCenterService extends SystemService {
UserProfileGroup userProfileGroup = UserProfileGroup.fromUser(getContext(), userId);
synchronized (mApiLock) {
+ safetySourceData =
+ AndroidLockScreenFix.maybeOverrideSafetySourceData(
+ getContext(), safetySourceId, safetySourceData);
+ safetyEvent =
+ SafetyEventFix.maybeOverrideSafetyEvent(
+ mSafetyCenterDataManager,
+ safetySourceId,
+ safetySourceData,
+ safetyEvent,
+ userId);
boolean hasUpdate =
mSafetyCenterDataManager.setSafetySourceData(
safetySourceData, safetySourceId, safetyEvent, packageName, userId);
@@ -298,9 +342,8 @@ public final class SafetyCenterService extends SystemService {
String safetySourceId, String packageName, @UserIdInt int userId) {
requireNonNull(safetySourceId);
requireNonNull(packageName);
- getContext()
- .enforceCallingOrSelfPermission(
- SEND_SAFETY_CENTER_UPDATE, "getSafetySourceData");
+ enforceAnyCallingOrSelfPermissions(
+ "getSafetySourceData", SEND_SAFETY_CENTER_UPDATE, MANAGE_SAFETY_CENTER);
if (!enforceCrossUserPermission("getSafetySourceData", userId)
|| !enforcePackage(Binder.getCallingUid(), packageName, userId)
|| !checkApiEnabled("getSafetySourceData")) {
@@ -342,7 +385,7 @@ public final class SafetyCenterService extends SystemService {
== SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED) {
safetyCenterErrorDetails =
new SafetyCenterErrorDetails(
- mSafetyCenterResourcesContext.getStringByName(
+ mSafetyCenterResourcesApk.getStringByName(
"resolving_action_error"));
}
if (hasUpdate) {
@@ -363,7 +406,10 @@ public final class SafetyCenterService extends SystemService {
|| !checkApiEnabled("refreshSafetySources")) {
return;
}
- startRefreshingSafetySources(refreshReason, userId);
+
+ synchronized (mApiLock) {
+ startRefreshingSafetySourcesLocked(refreshReason, userId);
+ }
}
@Override
@@ -380,7 +426,10 @@ public final class SafetyCenterService extends SystemService {
|| !checkApiEnabled("refreshSpecificSafetySources")) {
return;
}
- startRefreshingSafetySources(refreshReason, userId, safetySourceIds);
+
+ synchronized (mApiLock) {
+ startRefreshingSafetySourcesLocked(refreshReason, userId, safetySourceIds);
+ }
}
@Override
@@ -392,7 +441,7 @@ public final class SafetyCenterService extends SystemService {
// search works by adding all the entries very rarely (and relies on filtering them out
// instead).
if (!canUseSafetyCenter()) {
- Log.w(TAG, "Called getSafetyCenterConfig, but Safety Center is not supported");
+ Log.i(TAG, "Called getSafetyCenterConfig, but Safety Center is not supported");
return null;
}
@@ -504,7 +553,7 @@ public final class SafetyCenterService extends SystemService {
PendingIntent onDismissPendingIntent =
safetySourceIssue.getOnDismissPendingIntent();
if (onDismissPendingIntent != null
- && !dispatchPendingIntent(onDismissPendingIntent, null)) {
+ && !dispatchPendingIntent(onDismissPendingIntent)) {
Log.w(
TAG,
"Error dispatching dismissal for issue: "
@@ -634,13 +683,14 @@ public final class SafetyCenterService extends SystemService {
/** Enforces cross user permission and returns whether the user is valid. */
private boolean enforceCrossUserPermission(String message, @UserIdInt int userId) {
- UserUtils.enforceCrossUserPermission(userId, false, message, getContext());
+ UserUtils.enforceCrossUserPermission(
+ userId, /* allowAll= */ false, message, getContext());
if (!UserUtils.isUserExistent(userId, getContext())) {
Log.w(
TAG,
"Called "
+ message
- + " with user id "
+ + " with user id: "
+ userId
+ ", which does not correspond to an existing user");
return false;
@@ -650,7 +700,7 @@ public final class SafetyCenterService extends SystemService {
TAG,
"Called "
+ message
- + " with user id "
+ + " with user id: "
+ userId
+ ", which is an unsupported user");
return false;
@@ -676,7 +726,7 @@ public final class SafetyCenterService extends SystemService {
packageManager.getPackageUidAsUser(
packageName, PackageInfoFlags.of(0), userId);
} catch (NameNotFoundException e) {
- Log.e(TAG, "packageName=" + packageName + ", not found for userId=" + userId, e);
+ Log.w(TAG, "Package: " + packageName + ", not found for user id: " + userId, e);
return false;
}
if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID) {
@@ -684,9 +734,9 @@ public final class SafetyCenterService extends SystemService {
}
if (UserHandle.getAppId(callingUid) != UserHandle.getAppId(actualUid)) {
throw new SecurityException(
- "packageName="
+ "Package: "
+ packageName
- + ", does not belong to callingUid="
+ + ", does not belong to calling uid: "
+ callingUid);
}
return true;
@@ -719,9 +769,11 @@ public final class SafetyCenterService extends SystemService {
ParcelFileDescriptor err,
String[] args) {
return new SafetyCenterShellCommandHandler(
- getContext(), this, mDeviceSupportsSafetyCenter)
+ getContext(),
+ /* safetyCenterManager= */ this,
+ mDeviceSupportsSafetyCenter)
.exec(
- this,
+ /* target= */ this,
in.getFileDescriptor(),
out.getFileDescriptor(),
err.getFileDescriptor(),
@@ -793,12 +845,10 @@ public final class SafetyCenterService extends SystemService {
* value maps to {@link SafetyCenterManager#isSafetyCenterEnabled()}. It should only be
* registered if the device supports SafetyCenter and the {@link SafetyCenterConfig} was loaded
* successfully.
- *
- * <p>This listener is not thread-safe; it should be called on a single thread.
*/
- @NotThreadSafe
private final class SafetyCenterEnabledListener implements OnPropertiesChangedListener {
+ @GuardedBy("mApiLock")
private boolean mSafetyCenterEnabled;
@Override
@@ -807,41 +857,64 @@ public final class SafetyCenterService extends SystemService {
return;
}
boolean safetyCenterEnabled =
- properties.getBoolean(PROPERTY_SAFETY_CENTER_ENABLED, false);
- if (mSafetyCenterEnabled == safetyCenterEnabled) {
- return;
+ properties.getBoolean(PROPERTY_SAFETY_CENTER_ENABLED, SdkLevel.isAtLeastU());
+ synchronized (mApiLock) {
+ if (mSafetyCenterEnabled == safetyCenterEnabled) {
+ Log.i(
+ TAG,
+ "Safety Center is already "
+ + (mSafetyCenterEnabled ? "enabled" : "disabled")
+ + ", ignoring change");
+ return;
+ }
+ onSafetyCenterEnabledChangedLocked(safetyCenterEnabled);
}
- onSafetyCenterEnabledChanged(safetyCenterEnabled);
}
- private void setInitialState() {
+ @GuardedBy("mApiLock")
+ private void setInitialStateLocked() {
mSafetyCenterEnabled = SafetyCenterFlags.getSafetyCenterEnabled();
- Log.w(TAG, "SafetyCenter is " + (mSafetyCenterEnabled ? "enabled." : "disabled."));
+ if (mSafetyCenterEnabled) {
+ onApiInitEnabledLocked();
+ }
+ Log.i(TAG, "Safety Center is " + (mSafetyCenterEnabled ? "enabled" : "disabled"));
}
- private void onSafetyCenterEnabledChanged(boolean safetyCenterEnabled) {
- Log.w(TAG, "SafetyCenter is now " + (safetyCenterEnabled ? "enabled." : "disabled."));
-
+ @GuardedBy("mApiLock")
+ private void onSafetyCenterEnabledChangedLocked(boolean safetyCenterEnabled) {
if (safetyCenterEnabled) {
- onApiEnabled();
+ onApiEnabledLocked();
} else {
- onApiDisabled();
+ onApiDisabledLocked();
}
+
mSafetyCenterEnabled = safetyCenterEnabled;
+ Log.i(TAG, "Safety Center is now " + (mSafetyCenterEnabled ? "enabled" : "disabled"));
}
- private void onApiEnabled() {
- synchronized (mApiLock) {
- mSafetyCenterBroadcastDispatcher.sendEnabledChanged();
- }
+ @GuardedBy("mApiLock")
+ private void onApiInitEnabledLocked() {
+ mNotificationChannels.createAllChannelsForAllUsers(getContext());
}
- private void onApiDisabled() {
- synchronized (mApiLock) {
- clearDataLocked();
- mSafetyCenterListeners.clear();
- mSafetyCenterBroadcastDispatcher.sendEnabledChanged();
- }
+ @GuardedBy("mApiLock")
+ private void onApiEnabledLocked() {
+ mNotificationChannels.createAllChannelsForAllUsers(getContext());
+ mSafetyCenterBroadcastDispatcher.sendEnabledChanged();
+ }
+
+ @GuardedBy("mApiLock")
+ private void onApiDisabledLocked() {
+ // We're not clearing the Safety Center notification channels here. The reason for this
+ // is that the NotificationManager will post a runnable to cancel all associated
+ // notifications when clearing the channels. Given this happens asynchronously, this can
+ // leak between test cases and cause notifications that should be active to be cleared
+ // inadvertently. We're ok with the inconsistency because the channels are hidden
+ // somewhat deeply under Settings anyway, and we're unlikely to turn off Safety Center
+ // in production.
+ clearDataLocked();
+ mSafetyCenterListeners.clear();
+ mSafetyCenterBroadcastDispatcher.sendEnabledChanged();
}
}
@@ -870,28 +943,13 @@ public final class SafetyCenterService extends SystemService {
if (stillInFlight == null) {
return;
}
- boolean showErrorEntriesOnTimeout =
- SafetyCenterFlags.getShowErrorEntriesOnTimeout();
- boolean setError =
- showErrorEntriesOnTimeout
- && !RefreshReasons.isBackgroundRefresh(mRefreshReason);
+ boolean setError = !RefreshReasons.isBackgroundRefresh(mRefreshReason);
for (int i = 0; i < stillInFlight.size(); i++) {
mSafetyCenterDataManager.markSafetySourceRefreshTimedOut(
stillInFlight.valueAt(i), setError);
}
mSafetyCenterDataChangeNotifier.updateDataConsumers(mUserProfileGroup);
- if (!showErrorEntriesOnTimeout) {
- mSafetyCenterListeners.deliverErrorForUserProfileGroup(
- mUserProfileGroup,
- new SafetyCenterErrorDetails(
- mSafetyCenterResourcesContext.getStringByName(
- "refresh_timeout")));
- }
}
-
- Log.v(
- TAG,
- "Cleared refresh with broadcastId:" + mRefreshBroadcastId + " after a timeout");
}
@Override
@@ -938,8 +996,12 @@ public final class SafetyCenterService extends SystemService {
mSafetyCenterListeners.deliverErrorForUserProfileGroup(
mUserProfileGroup,
new SafetyCenterErrorDetails(
- mSafetyCenterResourcesContext.getStringByName(
+ mSafetyCenterResourcesApk.getStringByName(
"resolving_action_error")));
+ Log.w(
+ TAG,
+ "Resolving action timed out for: "
+ + toUserFriendlyString(mSafetyCenterIssueActionId));
}
}
@@ -961,18 +1023,38 @@ public final class SafetyCenterService extends SystemService {
/** {@link BroadcastReceiver} which handles Locale changes. */
private final class LocaleBroadcastReceiver extends BroadcastReceiver {
- private static final String TAG = "LocaleBroadcastReceiver";
+ private static final String TAG = "SafetyCenterLocaleBroad";
void register(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- context.registerReceiverForAllUsers(this, filter, null, null);
+ context.registerReceiverForAllUsers(
+ /* receiver= */ this,
+ filter,
+ /* broadcastPermission= */ null,
+ /* scheduler= */ null);
}
@Override
public void onReceive(Context context, Intent intent) {
+ if (!SafetyCenterFlags.getSafetyCenterEnabled()) {
+ Log.i(TAG, "Safety Center is disabled, ignoring intent: " + intent);
+ return;
+ }
+
+ String action = intent.getAction();
+ if (!TextUtils.equals(action, Intent.ACTION_LOCALE_CHANGED)) {
+ Log.w(TAG, "Received unexpected action: " + action);
+ return;
+ }
+
Log.d(TAG, "Locale changed broadcast received");
- mNotificationChannels.createAllChannelsForAllUsers(getContext());
+
+ int userId = ActivityManager.getCurrentUser();
+ synchronized (mApiLock) {
+ startRefreshingSafetySourcesLocked(REFRESH_REASON_DEVICE_LOCALE_CHANGE, userId);
+ mNotificationChannels.createAllChannelsForUser(getContext(), UserHandle.of(userId));
+ }
}
}
@@ -982,62 +1064,98 @@ public final class SafetyCenterService extends SystemService {
*/
private final class UserBroadcastReceiver extends BroadcastReceiver {
- private static final String TAG = "UserBroadcastReceiver";
+ private static final String TAG = "SafetyCenterUserBroadca";
void register(Context context) {
IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_USER_ADDED);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
- context.registerReceiverForAllUsers(this, filter, null, null);
+ context.registerReceiverForAllUsers(
+ /* receiver= */ this,
+ filter,
+ /* broadcastPermission= */ null,
+ /* scheduler= */ null);
}
@Override
public void onReceive(Context context, Intent intent) {
+ if (!SafetyCenterFlags.getSafetyCenterEnabled()) {
+ Log.i(TAG, "Safety Center is disabled, ignoring intent: " + intent);
+ return;
+ }
+
String action = intent.getAction();
if (action == null) {
- Log.w(TAG, "Received broadcast with null action!");
+ Log.w(TAG, "Received broadcast with null action");
return;
}
UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER, UserHandle.class);
if (userHandle == null) {
- Log.w(TAG, "Received " + action + " broadcast missing user extra!");
+ Log.w(TAG, "Received action: " + action + ", but missing user extra");
return;
}
int userId = userHandle.getIdentifier();
+ Log.d(TAG, "Received action: " + action + ", for user id: " + userId);
if (!UserProfileGroup.isSupported(userId, context)) {
Log.i(
TAG,
- "Received broadcast for user id "
+ "Received broadcast for user id: "
+ userId
+ ", which is an unsupported user");
return;
}
- Log.d(TAG, "Received " + action + " broadcast for user " + userId);
switch (action) {
case Intent.ACTION_USER_REMOVED:
case Intent.ACTION_MANAGED_PROFILE_REMOVED:
- removeUser(userId, true);
+ removeUserAndData(userId);
break;
case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
- removeUser(userId, false);
- // fall through!
- case Intent.ACTION_USER_ADDED:
+ removeUser(userId);
+ break;
+ case Intent.ACTION_USER_SWITCHED:
+ if (userId != ActivityManager.getCurrentUser()) {
+ Log.w(
+ TAG,
+ "Received broadcast for user id: "
+ + userId
+ + ", which is not the current user");
+ return;
+ }
+ // Fall through
case Intent.ACTION_MANAGED_PROFILE_ADDED:
case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
- startRefreshingSafetySources(REFRESH_REASON_OTHER, userId);
- mNotificationChannels.createAllChannelsForUser(getContext(), userHandle);
+ if (!UserUtils.isUserExistent(userId, getContext())) {
+ Log.w(
+ TAG,
+ "Received broadcast for user id: "
+ + userId
+ + ", which does not exist");
+ return;
+ }
+ synchronized (mApiLock) {
+ startRefreshingSafetySourcesLocked(REFRESH_REASON_OTHER, userId);
+ mNotificationChannels.createAllChannelsForUser(getContext(), userHandle);
+ }
break;
}
}
}
+ private void removeUserAndData(@UserIdInt int userId) {
+ removeUser(userId, /* clearDataPermanently= */ true);
+ }
+
+ private void removeUser(@UserIdInt int userId) {
+ removeUser(userId, /* clearDataPermanently= */ false);
+ }
+
private void removeUser(@UserIdInt int userId, boolean clearDataPermanently) {
UserProfileGroup userProfileGroup = UserProfileGroup.fromUser(getContext(), userId);
synchronized (mApiLock) {
@@ -1053,31 +1171,44 @@ public final class SafetyCenterService extends SystemService {
}
}
- private void startRefreshingSafetySources(
+ @GuardedBy("mApiLock")
+ private void startRefreshingSafetySourcesLocked(
@RefreshReason int refreshReason, @UserIdInt int userId) {
- startRefreshingSafetySources(refreshReason, userId, null);
+ startRefreshingSafetySourcesLocked(
+ refreshReason,
+ UserProfileGroup.fromUser(getContext(), userId),
+ /* selectedSafetySourceIds= */ null);
}
- private void startRefreshingSafetySources(
+ @GuardedBy("mApiLock")
+ private void startRefreshingSafetySourcesLocked(
@RefreshReason int refreshReason,
@UserIdInt int userId,
+ List<String> selectedSafetySourceIds) {
+ startRefreshingSafetySourcesLocked(
+ refreshReason,
+ UserProfileGroup.fromUser(getContext(), userId),
+ selectedSafetySourceIds);
+ }
+
+ @GuardedBy("mApiLock")
+ private void startRefreshingSafetySourcesLocked(
+ @RefreshReason int refreshReason,
+ UserProfileGroup userProfileGroup,
@Nullable List<String> selectedSafetySourceIds) {
- UserProfileGroup userProfileGroup = UserProfileGroup.fromUser(getContext(), userId);
- synchronized (mApiLock) {
- String refreshBroadcastId =
- mSafetyCenterBroadcastDispatcher.sendRefreshSafetySources(
- refreshReason, userProfileGroup, selectedSafetySourceIds);
- if (refreshBroadcastId == null) {
- return;
- }
+ String refreshBroadcastId =
+ mSafetyCenterBroadcastDispatcher.sendRefreshSafetySources(
+ refreshReason, userProfileGroup, selectedSafetySourceIds);
+ if (refreshBroadcastId == null) {
+ return;
+ }
- RefreshTimeout refreshTimeout =
- new RefreshTimeout(refreshBroadcastId, refreshReason, userProfileGroup);
- mSafetyCenterTimeouts.add(
- refreshTimeout, SafetyCenterFlags.getRefreshSourcesTimeout(refreshReason));
+ RefreshTimeout refreshTimeout =
+ new RefreshTimeout(refreshBroadcastId, refreshReason, userProfileGroup);
+ mSafetyCenterTimeouts.add(
+ refreshTimeout, SafetyCenterFlags.getRefreshSourcesTimeout(refreshReason));
- mSafetyCenterDataChangeNotifier.updateDataConsumers(userProfileGroup);
- }
+ mSafetyCenterDataChangeNotifier.updateDataConsumers(userProfileGroup);
}
/**
@@ -1091,7 +1222,7 @@ public final class SafetyCenterService extends SystemService {
safetyCenterIssueActionId.getSafetyCenterIssueKey();
UserProfileGroup userProfileGroup =
UserProfileGroup.fromUser(getContext(), safetyCenterIssueKey.getUserId());
- executeIssueActionInternal(safetyCenterIssueActionId, userProfileGroup, null);
+ executeIssueActionInternal(safetyCenterIssueActionId, userProfileGroup, /* taskId= */ null);
}
private void executeIssueActionInternal(
@@ -1120,16 +1251,19 @@ public final class SafetyCenterService extends SystemService {
CharSequence errorMessage;
if (safetySourceIssueAction.willResolve()) {
errorMessage =
- mSafetyCenterResourcesContext.getStringByName("resolving_action_error");
+ mSafetyCenterResourcesApk.getStringByName("resolving_action_error");
} else {
- errorMessage =
- mSafetyCenterResourcesContext.getStringByName("redirecting_error");
+ errorMessage = mSafetyCenterResourcesApk.getStringByName("redirecting_error");
}
mSafetyCenterListeners.deliverErrorForUserProfileGroup(
userProfileGroup, new SafetyCenterErrorDetails(errorMessage));
return;
}
if (safetySourceIssueAction.willResolve()) {
+ Log.d(
+ TAG,
+ "Starting resolving action for: "
+ + toUserFriendlyString(safetyCenterIssueActionId));
mSafetyCenterDataManager.markSafetyCenterIssueActionInFlight(
safetyCenterIssueActionId);
ResolvingActionTimeout resolvingActionTimeout =
@@ -1141,6 +1275,10 @@ public final class SafetyCenterService extends SystemService {
}
}
+ private boolean dispatchPendingIntent(PendingIntent pendingIntent) {
+ return dispatchPendingIntent(pendingIntent, /* launchTaskId= */ null);
+ }
+
private boolean dispatchPendingIntent(
PendingIntent pendingIntent, @Nullable Integer launchTaskId) {
if (launchTaskId != null
diff --git a/service/java/com/android/safetycenter/SafetyCenterShellCommandHandler.java b/service/java/com/android/safetycenter/SafetyCenterShellCommandHandler.java
index 87e3372f7..82983f0bb 100644
--- a/service/java/com/android/safetycenter/SafetyCenterShellCommandHandler.java
+++ b/service/java/com/android/safetycenter/SafetyCenterShellCommandHandler.java
@@ -16,7 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_DEVICE_LOCALE_CHANGE;
import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_DEVICE_REBOOT;
import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_OTHER;
@@ -27,14 +26,13 @@ import static android.safetycenter.SafetyCenterManager.REFRESH_REASON_SAFETY_CEN
import static java.util.Collections.unmodifiableMap;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.RemoteException;
import android.safetycenter.ISafetyCenterManager;
import android.safetycenter.SafetyCenterManager.RefreshReason;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.BasicShellCommandHandler;
import com.android.modules.utils.build.SdkLevel;
@@ -48,7 +46,6 @@ import java.util.Map;
*
* <p>Example usage: $ adb shell cmd safety_center refresh --reason PAGE_OPEN --user 10
*/
-@RequiresApi(TIRAMISU)
final class SafetyCenterShellCommandHandler extends BasicShellCommandHandler {
private static final Map<String, Integer> REASONS = createReasonMap();
@@ -89,11 +86,18 @@ final class SafetyCenterShellCommandHandler extends BasicShellCommandHandler {
return handleDefaultCommands(cmd);
}
} catch (RemoteException | IllegalArgumentException e) {
- e.printStackTrace(getErrPrintWriter());
+ printError(e);
return 1;
}
}
+ // We want to log the stack trace on a specific PrintWriter here, this is a false positive as
+ // the warning does not consider the overload that takes a PrintWriter as an argument (yet).
+ @SuppressWarnings("CatchAndPrintStackTrace")
+ private void printError(Throwable error) {
+ error.printStackTrace(getErrPrintWriter());
+ }
+
private int onEnabled() throws RemoteException {
getOutPrintWriter().println(mSafetyCenterManager.isSafetyCenterEnabled());
return 0;
diff --git a/service/java/com/android/safetycenter/SafetyCenterTimeouts.java b/service/java/com/android/safetycenter/SafetyCenterTimeouts.java
index f8bfd691e..b37951fb1 100644
--- a/service/java/com/android/safetycenter/SafetyCenterTimeouts.java
+++ b/service/java/com/android/safetycenter/SafetyCenterTimeouts.java
@@ -16,12 +16,8 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.os.Handler;
-import androidx.annotation.RequiresApi;
-
import com.android.permission.util.ForegroundThread;
import java.io.PrintWriter;
@@ -36,7 +32,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterTimeouts {
diff --git a/service/java/com/android/safetycenter/SafetySourceIssueInfo.java b/service/java/com/android/safetycenter/SafetySourceIssueInfo.java
index 51e6567d7..0dfa7c814 100644
--- a/service/java/com/android/safetycenter/SafetySourceIssueInfo.java
+++ b/service/java/com/android/safetycenter/SafetySourceIssueInfo.java
@@ -16,8 +16,6 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriendlyString;
import android.annotation.UserIdInt;
@@ -25,8 +23,6 @@ import android.safetycenter.SafetySourceIssue;
import android.safetycenter.config.SafetySource;
import android.safetycenter.config.SafetySourcesGroup;
-import androidx.annotation.RequiresApi;
-
import com.android.safetycenter.internaldata.SafetyCenterIssueKey;
import java.util.Objects;
@@ -36,7 +32,6 @@ import java.util.Objects;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetySourceIssueInfo {
private final SafetySourceIssue mSafetySourceIssue;
@@ -65,6 +60,7 @@ public final class SafetySourceIssueInfo {
public SafetyCenterIssueKey getSafetyCenterIssueKey() {
return mSafetyCenterIssueKey;
}
+
/** Returns the {@link SafetySourceIssue}. */
public SafetySourceIssue getSafetySourceIssue() {
return mSafetySourceIssue;
diff --git a/service/java/com/android/safetycenter/SafetySourceIssues.java b/service/java/com/android/safetycenter/SafetySourceIssues.java
new file mode 100644
index 000000000..dc3c2a83e
--- /dev/null
+++ b/service/java/com/android/safetycenter/SafetySourceIssues.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 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.safetycenter;
+
+import android.safetycenter.SafetySourceIssue;
+
+import androidx.annotation.Nullable;
+
+import com.android.modules.utils.build.SdkLevel;
+
+import java.util.List;
+
+/**
+ * A helper class to facilitate working with {@link SafetySourceIssue} objects.
+ *
+ * @hide
+ */
+public final class SafetySourceIssues {
+
+ /**
+ * Returns the {@link SafetySourceIssue.Action} with the given action ID belonging to the given
+ * {@link SafetySourceIssue} or {@code null} if no such action is present.
+ *
+ * <p>The action will either belong to the issue directly from {@link
+ * SafetySourceIssue#getActions()} or via {@link SafetySourceIssue#getCustomNotification()} if
+ * the issue has a custom notification.
+ */
+ @Nullable
+ public static SafetySourceIssue.Action findAction(SafetySourceIssue issue, String actionId) {
+ SafetySourceIssue.Action action = null;
+ if (SdkLevel.isAtLeastU() && issue.getCustomNotification() != null) {
+ action = findAction(issue.getCustomNotification().getActions(), actionId);
+ }
+ if (action == null) {
+ action = findAction(issue.getActions(), actionId);
+ }
+ return action;
+ }
+
+ @Nullable
+ private static SafetySourceIssue.Action findAction(
+ List<SafetySourceIssue.Action> actions, String actionId) {
+ for (int i = 0; i < actions.size(); i++) {
+ SafetySourceIssue.Action action = actions.get(i);
+ if (action.getId().equals(actionId)) {
+ return action;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns {@code true} if {@code actionId} corresponds to a "primary" action of the given
+ * {@code issue}, or {@code false} if the action is not the primary or if no action with the
+ * given ID is found.
+ *
+ * <p>A primary action is the first action of either the issue, or its custom notification.
+ */
+ public static boolean isPrimaryAction(SafetySourceIssue issue, String actionId) {
+ boolean isPrimaryNotificationAction =
+ SdkLevel.isAtLeastU()
+ && issue.getCustomNotification() != null
+ && matchesFirst(issue.getCustomNotification().getActions(), actionId);
+ boolean isPrimaryIssueAction = matchesFirst(issue.getActions(), actionId);
+ return isPrimaryNotificationAction || isPrimaryIssueAction;
+ }
+
+ private static boolean matchesFirst(List<SafetySourceIssue.Action> actions, String actionId) {
+ return !actions.isEmpty() && actions.get(0).getId().equals(actionId);
+ }
+
+ private SafetySourceIssues() {}
+}
diff --git a/service/java/com/android/safetycenter/SafetySourceKey.java b/service/java/com/android/safetycenter/SafetySourceKey.java
index 511fbef73..9e1400e30 100644
--- a/service/java/com/android/safetycenter/SafetySourceKey.java
+++ b/service/java/com/android/safetycenter/SafetySourceKey.java
@@ -16,13 +16,9 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.annotation.UserIdInt;
import android.safetycenter.SafetySourceData;
-import androidx.annotation.RequiresApi;
-
import java.util.Objects;
/**
@@ -32,7 +28,7 @@ import java.util.Objects;
* @hide
*/
// TODO(b/219697341): Look into using AutoValue for this data class.
-@RequiresApi(TIRAMISU)
+
public final class SafetySourceKey {
private final String mSourceId;
diff --git a/service/java/com/android/safetycenter/SafetySources.java b/service/java/com/android/safetycenter/SafetySources.java
index c0b0bdc48..02d83d27b 100644
--- a/service/java/com/android/safetycenter/SafetySources.java
+++ b/service/java/com/android/safetycenter/SafetySources.java
@@ -16,20 +16,15 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.safetycenter.SafetySourceData;
import android.safetycenter.config.SafetySource;
import android.util.Log;
-import androidx.annotation.RequiresApi;
-
/**
* A helper class to facilitate working with {@link SafetySource} objects.
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetySources {
private static final String TAG = "SafetySources";
diff --git a/service/java/com/android/safetycenter/SafetySourcesGroups.java b/service/java/com/android/safetycenter/SafetySourcesGroups.java
index 5233302aa..a86eccada 100644
--- a/service/java/com/android/safetycenter/SafetySourcesGroups.java
+++ b/service/java/com/android/safetycenter/SafetySourcesGroups.java
@@ -16,16 +16,11 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.safetycenter.config.SafetySourcesGroup;
-import androidx.annotation.RequiresApi;
-
import com.android.modules.utils.build.SdkLevel;
/** Static utilities for working with {@link SafetySourcesGroup} objects. */
-@RequiresApi(TIRAMISU)
final class SafetySourcesGroups {
/**
diff --git a/service/java/com/android/safetycenter/UserProfileGroup.java b/service/java/com/android/safetycenter/UserProfileGroup.java
index 8d3adc573..74b9b136f 100644
--- a/service/java/com/android/safetycenter/UserProfileGroup.java
+++ b/service/java/com/android/safetycenter/UserProfileGroup.java
@@ -16,11 +16,8 @@
package com.android.safetycenter;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static java.util.Objects.requireNonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -30,7 +27,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.UserUtils;
@@ -45,7 +42,6 @@ import java.util.Objects;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class UserProfileGroup {
private static final String TAG = "UserProfileGroup";
@@ -141,9 +137,9 @@ public final class UserProfileGroup {
Arrays.copyOf(
managedRunningProfilesUserIds, managedRunningProfilesUserIdsLen));
if (!userProfileGroup.contains(userId)) {
- Log.w(
+ Log.i(
TAG,
- "User id " + userId + " does not belong to " + userProfileGroup,
+ "User id: " + userId + " does not belong to: " + userProfileGroup,
new Exception());
}
return userProfileGroup;
@@ -167,7 +163,8 @@ public final class UserProfileGroup {
return context;
} else {
try {
- return context.createPackageContextAsUser(context.getPackageName(), 0, userHandle);
+ return context.createPackageContextAsUser(
+ context.getPackageName(), /* flags= */ 0, userHandle);
} catch (PackageManager.NameNotFoundException doesNotHappen) {
throw new IllegalStateException(doesNotHappen);
}
@@ -232,9 +229,9 @@ public final class UserProfileGroup {
profileParentAndManagedRunningProfilesUserIds[0] = mProfileParentUserId;
System.arraycopy(
mManagedRunningProfilesUserIds,
- 0,
+ /* srcPos= */ 0,
profileParentAndManagedRunningProfilesUserIds,
- 1,
+ /* destPos= */ 1,
mManagedRunningProfilesUserIds.length);
return profileParentAndManagedRunningProfilesUserIds;
}
diff --git a/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java b/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
index 5db3cfbad..e46ba2f4d 100644
--- a/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
+++ b/service/java/com/android/safetycenter/data/AndroidLockScreenFix.java
@@ -16,9 +16,6 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -30,7 +27,7 @@ import android.safetycenter.SafetySourceIssue;
import android.safetycenter.SafetySourceStatus;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.safetycenter.PendingIntentFactory;
@@ -41,9 +38,10 @@ import java.util.List;
/**
* A class to work around an issue with the {@code AndroidLockScreen} safety source, by potentially
* overriding its {@link SafetySourceData}.
+ *
+ * @hide
*/
-@RequiresApi(TIRAMISU)
-final class AndroidLockScreenFix {
+public final class AndroidLockScreenFix {
private static final String TAG = "AndroidLockScreenFix";
@@ -73,7 +71,7 @@ final class AndroidLockScreenFix {
* created (the key does take into account the request code).
*/
@Nullable
- static SafetySourceData maybeOverrideSafetySourceData(
+ public static SafetySourceData maybeOverrideSafetySourceData(
Context context, String sourceId, @Nullable SafetySourceData safetySourceData) {
if (safetySourceData == null) {
return null;
@@ -119,7 +117,9 @@ final class AndroidLockScreenFix {
safetySourceStatus.getSeverityLevel())
.setPendingIntent(
overridePendingIntent(
- context, safetySourceStatus.getPendingIntent(), false))
+ context,
+ safetySourceStatus.getPendingIntent(),
+ /* isIconAction= */ false))
.setEnabled(safetySourceStatus.isEnabled());
SafetySourceStatus.IconAction iconAction = safetySourceStatus.getIconAction();
if (iconAction != null) {
@@ -134,7 +134,8 @@ final class AndroidLockScreenFix {
Context context, SafetySourceStatus.IconAction iconAction) {
return new SafetySourceStatus.IconAction(
iconAction.getIconType(),
- overridePendingIntent(context, iconAction.getPendingIntent(), true));
+ overridePendingIntent(
+ context, iconAction.getPendingIntent(), /* isIconAction= */ true));
}
private static SafetySourceIssue overrideTiramisuSafetySourceIssue(
@@ -163,7 +164,8 @@ final class AndroidLockScreenFix {
return new SafetySourceIssue.Action.Builder(
action.getId(),
action.getLabel(),
- overridePendingIntent(context, action.getPendingIntent(), false))
+ overridePendingIntent(
+ context, action.getPendingIntent(), /* isIconAction= */ false))
.setWillResolve(action.willResolve())
.setSuccessMessage(action.getSuccessMessage())
.build();
@@ -206,7 +208,7 @@ final class AndroidLockScreenFix {
// This is important because there are scenarios where the Settings app provides different
// pending intents (e.g. in the work profile), and in this case we shouldn't override them.
if (isIconAction) {
- Log.w(
+ Log.i(
TAG,
"Replacing " + ANDROID_LOCK_SCREEN_SOURCE_ID + " icon action pending intent");
return PendingIntentFactory.getActivityPendingIntent(
@@ -215,7 +217,7 @@ final class AndroidLockScreenFix {
newLockScreenIconActionIntent(settingsPackageName),
PendingIntent.FLAG_IMMUTABLE);
}
- Log.w(TAG, "Replacing " + ANDROID_LOCK_SCREEN_SOURCE_ID + " entry or issue pending intent");
+ Log.i(TAG, "Replacing " + ANDROID_LOCK_SCREEN_SOURCE_ID + " entry or issue pending intent");
return PendingIntentFactory.getActivityPendingIntent(
settingsPackageContext,
ANDROID_LOCK_SCREEN_ENTRY_REQ_CODE,
diff --git a/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java b/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java
index 734732401..dff7c4339 100644
--- a/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java
+++ b/service/java/com/android/safetycenter/data/SafetyCenterDataManager.java
@@ -16,11 +16,11 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
+import static android.Manifest.permission.MANAGE_SAFETY_CENTER;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.safetycenter.logging.SafetyCenterStatsdLogger.toSystemEventResult;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.safetycenter.SafetyCenterData;
@@ -30,9 +30,10 @@ import android.safetycenter.SafetySourceErrorDetails;
import android.safetycenter.SafetySourceIssue;
import android.safetycenter.config.SafetyCenterConfig;
import android.safetycenter.config.SafetySourcesGroup;
+import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.safetycenter.ApiLock;
import com.android.safetycenter.SafetyCenterConfigReader;
@@ -60,12 +61,12 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterDataManager {
private static final String TAG = "SafetyCenterDataManager";
+ private final Context mContext;
private final SafetyCenterRefreshTracker mSafetyCenterRefreshTracker;
private final SafetySourceDataRepository mSafetySourceDataRepository;
private final SafetyCenterIssueDismissalRepository mSafetyCenterIssueDismissalRepository;
@@ -81,6 +82,7 @@ public final class SafetyCenterDataManager {
SafetyCenterConfigReader safetyCenterConfigReader,
SafetyCenterRefreshTracker safetyCenterRefreshTracker,
ApiLock apiLock) {
+ mContext = context;
mSafetyCenterRefreshTracker = safetyCenterRefreshTracker;
mSafetyCenterInFlightIssueActionRepository =
new SafetyCenterInFlightIssueActionRepository(context);
@@ -88,7 +90,6 @@ public final class SafetyCenterDataManager {
new SafetyCenterIssueDismissalRepository(apiLock, safetyCenterConfigReader);
mSafetySourceDataRepository =
new SafetySourceDataRepository(
- context,
mSafetyCenterInFlightIssueActionRepository,
mSafetyCenterIssueDismissalRepository);
mSafetyCenterIssueRepository =
@@ -134,10 +135,14 @@ public final class SafetyCenterDataManager {
String packageName,
@UserIdInt int userId) {
if (!mSafetySourceDataValidator.validateRequest(
- safetySourceData, safetySourceId, packageName, userId)) {
+ safetySourceData,
+ /* callerCanAccessAnySource= */ false,
+ safetySourceId,
+ packageName,
+ userId)) {
return false;
}
- SafetySourceKey key = SafetySourceKey.of(safetySourceId, userId);
+ SafetySourceKey safetySourceKey = SafetySourceKey.of(safetySourceId, userId);
// Must fetch refresh reason before calling processSafetyEvent because the latter may
// complete and clear the current refresh.
@@ -147,11 +152,15 @@ public final class SafetyCenterDataManager {
refreshReason = mSafetyCenterRefreshTracker.getRefreshReason();
}
- boolean sourceDataDiffers =
- mSafetySourceDataRepository.setSafetySourceData(
- safetySourceData, safetySourceId, userId);
+ // It is important to process the event first as it relies on the data available prior to
+ // changing it.
+ boolean sourceDataWillChange =
+ !mSafetySourceDataRepository.sourceHasData(safetySourceKey, safetySourceData);
boolean eventCausedChange =
- processSafetyEvent(safetySourceId, safetyEvent, userId, false, sourceDataDiffers);
+ processSafetyEvent(
+ safetySourceKey, safetyEvent, /* isError= */ false, sourceDataWillChange);
+ boolean sourceDataDiffers =
+ mSafetySourceDataRepository.setSafetySourceData(safetySourceKey, safetySourceData);
boolean safetyCenterDataChanged = sourceDataDiffers || eventCausedChange;
if (safetyCenterDataChanged) {
@@ -159,7 +168,12 @@ public final class SafetyCenterDataManager {
}
mSafetySourceStateCollectedLogger.writeSourceUpdatedAtom(
- key, safetySourceData, refreshReason, sourceDataDiffers, userId, safetyEvent);
+ safetySourceKey,
+ safetySourceData,
+ refreshReason,
+ sourceDataDiffers,
+ userId,
+ safetyEvent);
return safetyCenterDataChanged;
}
@@ -199,11 +213,15 @@ public final class SafetyCenterDataManager {
String packageName,
@UserIdInt int userId) {
if (!mSafetySourceDataValidator.validateRequest(
- null, safetySourceId, packageName, userId)) {
+ /* safetySourceData= */ null,
+ /* callerCanAccessAnySource= */ false,
+ safetySourceId,
+ packageName,
+ userId)) {
return false;
}
SafetyEvent safetyEvent = safetySourceErrorDetails.getSafetyEvent();
- SafetySourceKey key = SafetySourceKey.of(safetySourceId, userId);
+ SafetySourceKey safetySourceKey = SafetySourceKey.of(safetySourceId, userId);
// Must fetch refresh reason before calling processSafetyEvent because the latter may
// complete and clear the current refresh.
@@ -213,11 +231,15 @@ public final class SafetyCenterDataManager {
refreshReason = mSafetyCenterRefreshTracker.getRefreshReason();
}
+ // It is important to process the event first as it relies on the data available prior to
+ // changing it.
+ boolean sourceDataWillChange = !mSafetySourceDataRepository.sourceHasError(safetySourceKey);
+ boolean eventCausedChange =
+ processSafetyEvent(
+ safetySourceKey, safetyEvent, /* isError= */ true, sourceDataWillChange);
boolean sourceDataDiffers =
mSafetySourceDataRepository.reportSafetySourceError(
- safetySourceErrorDetails, safetySourceId, userId);
- boolean eventCausedChange =
- processSafetyEvent(safetySourceId, safetyEvent, userId, true, sourceDataDiffers);
+ safetySourceKey, safetySourceErrorDetails);
boolean safetyCenterDataChanged = sourceDataDiffers || eventCausedChange;
if (safetyCenterDataChanged) {
@@ -225,7 +247,12 @@ public final class SafetyCenterDataManager {
}
mSafetySourceStateCollectedLogger.writeSourceUpdatedAtom(
- key, null, refreshReason, sourceDataDiffers, userId, safetyEvent);
+ safetySourceKey,
+ /* safetySourceData= */ null,
+ refreshReason,
+ sourceDataDiffers,
+ userId,
+ safetyEvent);
return safetyCenterDataChanged;
}
@@ -389,6 +416,11 @@ public final class SafetyCenterDataManager {
safetyCenterIssueActionId);
}
+ /** Returns a list of IDs of in-flight actions for the given source and user */
+ ArraySet<SafetyCenterIssueActionId> getInFlightActions(String sourceId, @UserIdInt int userId) {
+ return mSafetyCenterInFlightIssueActionRepository.getInFlightActions(sourceId, userId);
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
////////////////////// SafetySourceDataRepository ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -406,8 +438,14 @@ public final class SafetyCenterDataManager {
@Nullable
public SafetySourceData getSafetySourceData(
String safetySourceId, String packageName, @UserIdInt int userId) {
+ boolean callerCanAccessAnySource =
+ mContext.checkCallingOrSelfPermission(MANAGE_SAFETY_CENTER) == PERMISSION_GRANTED;
if (!mSafetySourceDataValidator.validateRequest(
- null, safetySourceId, packageName, userId)) {
+ /* safetySourceData= */ null,
+ callerCanAccessAnySource,
+ safetySourceId,
+ packageName,
+ userId)) {
return null;
}
return mSafetySourceDataRepository.getSafetySourceData(
@@ -472,38 +510,37 @@ public final class SafetyCenterDataManager {
}
private boolean processSafetyEvent(
- String safetySourceId,
+ SafetySourceKey safetySourceKey,
SafetyEvent safetyEvent,
- @UserIdInt int userId,
boolean isError,
- boolean sourceDataChanged) {
+ boolean sourceDataWillChange) {
int type = safetyEvent.getType();
switch (type) {
case SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED:
String refreshBroadcastId = safetyEvent.getRefreshBroadcastId();
if (refreshBroadcastId == null) {
- Log.w(TAG, "No refresh broadcast id in SafetyEvent of type " + type);
+ Log.w(TAG, "No refresh broadcast id in SafetyEvent of type: " + type);
return false;
}
return mSafetyCenterRefreshTracker.reportSourceRefreshCompleted(
- refreshBroadcastId, safetySourceId, userId, !isError, sourceDataChanged);
+ refreshBroadcastId, safetySourceKey, !isError, sourceDataWillChange);
case SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED:
case SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED:
String safetySourceIssueId = safetyEvent.getSafetySourceIssueId();
if (safetySourceIssueId == null) {
- Log.w(TAG, "No safety source issue id in SafetyEvent of type " + type);
+ Log.w(TAG, "No safety source issue id in SafetyEvent of type: " + type);
return false;
}
String safetySourceIssueActionId = safetyEvent.getSafetySourceIssueActionId();
if (safetySourceIssueActionId == null) {
- Log.w(TAG, "No safety source issue action id in SafetyEvent of type " + type);
+ Log.w(TAG, "No safety source issue action id in SafetyEvent of type: " + type);
return false;
}
SafetyCenterIssueKey safetyCenterIssueKey =
SafetyCenterIssueKey.newBuilder()
- .setSafetySourceId(safetySourceId)
+ .setSafetySourceId(safetySourceKey.getSourceId())
.setSafetySourceIssueId(safetySourceIssueId)
- .setUserId(userId)
+ .setUserId(safetySourceKey.getUserId())
.build();
SafetyCenterIssueActionId safetyCenterIssueActionId =
SafetyCenterIssueActionId.newBuilder()
diff --git a/service/java/com/android/safetycenter/data/SafetyCenterInFlightIssueActionRepository.java b/service/java/com/android/safetycenter/data/SafetyCenterInFlightIssueActionRepository.java
index 4fa6e5363..82eb3a6c7 100644
--- a/service/java/com/android/safetycenter/data/SafetyCenterInFlightIssueActionRepository.java
+++ b/service/java/com/android/safetycenter/data/SafetyCenterInFlightIssueActionRepository.java
@@ -16,33 +16,30 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriendlyString;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.SystemClock;
import android.safetycenter.SafetySourceIssue;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.UserUtils;
+import com.android.safetycenter.SafetySourceIssues;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
import com.android.safetycenter.internaldata.SafetyCenterIssueKey;
import com.android.safetycenter.logging.SafetyCenterStatsdLogger;
import java.io.PrintWriter;
import java.time.Duration;
-import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
/** Maintains data about in-flight issue actions. */
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterInFlightIssueActionRepository {
@@ -113,6 +110,19 @@ final class SafetyCenterInFlightIssueActionRepository {
return mSafetyCenterIssueActionsInFlight.containsKey(safetyCenterIssueActionId);
}
+ /** Returns a list of IDs of in-flight actions for the given source and user */
+ ArraySet<SafetyCenterIssueActionId> getInFlightActions(String sourceId, @UserIdInt int userId) {
+ ArraySet<SafetyCenterIssueActionId> result = new ArraySet<>();
+ for (int i = 0; i < mSafetyCenterIssueActionsInFlight.size(); i++) {
+ SafetyCenterIssueActionId actionId = mSafetyCenterIssueActionsInFlight.keyAt(i);
+ SafetyCenterIssueKey issueKey = actionId.getSafetyCenterIssueKey();
+ if (sourceId.equals(issueKey.getSafetySourceId()) && issueKey.getUserId() == userId) {
+ result.add(actionId);
+ }
+ }
+ return result;
+ }
+
/**
* Returns {@link SafetySourceIssue.Action} identified by the given {@link
* SafetyCenterIssueActionId} and {@link SafetySourceIssue}.
@@ -125,18 +135,8 @@ final class SafetyCenterInFlightIssueActionRepository {
return null;
}
- List<SafetySourceIssue.Action> safetySourceIssueActions = safetySourceIssue.getActions();
- for (int i = 0; i < safetySourceIssueActions.size(); i++) {
- SafetySourceIssue.Action safetySourceIssueAction = safetySourceIssueActions.get(i);
-
- if (safetyCenterIssueActionId
- .getSafetySourceIssueActionId()
- .equals(safetySourceIssueAction.getId())) {
- return safetySourceIssueAction;
- }
- }
-
- return null;
+ return SafetySourceIssues.findAction(
+ safetySourceIssue, safetyCenterIssueActionId.getSafetySourceIssueActionId());
}
/** Dumps in-flight action data for debugging purposes. */
diff --git a/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java b/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java
index d5218a0aa..1a86640dd 100644
--- a/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java
+++ b/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java
@@ -16,7 +16,6 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriendlyString;
@@ -27,13 +26,13 @@ import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
import static java.util.Collections.unmodifiableSet;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.safetycenter.config.SafetySourcesGroup;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.android.safetycenter.SafetySourceIssueInfo;
@@ -48,7 +47,6 @@ import java.util.Set;
import javax.annotation.concurrent.NotThreadSafe;
/** Deduplicates issues based on deduplication info provided by the source and the issue. */
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterIssueDeduplicator {
@@ -56,7 +54,6 @@ final class SafetyCenterIssueDeduplicator {
private final SafetyCenterIssueDismissalRepository mSafetyCenterIssueDismissalRepository;
- @RequiresApi(TIRAMISU)
SafetyCenterIssueDeduplicator(
SafetyCenterIssueDismissalRepository safetyCenterIssueDismissalRepository) {
this.mSafetyCenterIssueDismissalRepository = safetyCenterIssueDismissalRepository;
@@ -72,7 +69,7 @@ final class SafetyCenterIssueDeduplicator {
* <p>In case any issue, in the bucket of duplicate issues, was dismissed, all issues of the
* same or lower severity will be dismissed as well.
*
- * @return deduplicated list of issues, and some other information gathere in the deduplication
+ * @return deduplicated list of issues, and some other information gathered in the deduplication
* process
*/
@RequiresApi(UPSIDE_DOWN_CAKE)
@@ -123,7 +120,7 @@ final class SafetyCenterIssueDeduplicator {
for (int i = 0; i < dedupBuckets.size(); i++) {
List<SafetySourceIssueInfo> duplicates = dedupBuckets.valueAt(i);
if (duplicates.isEmpty()) {
- Log.w(TAG, "List of duplicates in a dedupBucket is empty");
+ Log.w(TAG, "List of duplicates in a deduplication bucket is empty");
continue;
}
@@ -164,7 +161,7 @@ final class SafetyCenterIssueDeduplicator {
}
/**
- * Handles dismissals logic: in each bucket, dismissal details of the top (highest priority)
+ * Handles dismissals logic: in each bucket, dismissal details of the highest priority (top)
* dismissed issue will be copied to all other duplicate issues in that bucket, that are of
* equal or lower severity (not priority). Notification-dismissal details are handled similarly.
*/
@@ -329,7 +326,6 @@ final class SafetyCenterIssueDeduplicator {
}
/** Encapsulates deduplication result along with some additional information. */
- @RequiresApi(TIRAMISU) // to simplify code and minimize code path differences across SDKs
static final class DeduplicationInfo {
private final List<SafetySourceIssueInfo> mDeduplicatedIssues;
private final List<SafetySourceIssueInfo> mFilteredOutDuplicates;
diff --git a/service/java/com/android/safetycenter/data/SafetyCenterIssueDismissalRepository.java b/service/java/com/android/safetycenter/data/SafetyCenterIssueDismissalRepository.java
index bc9bfb2d6..c84aa54f3 100644
--- a/service/java/com/android/safetycenter/data/SafetyCenterIssueDismissalRepository.java
+++ b/service/java/com/android/safetycenter/data/SafetyCenterIssueDismissalRepository.java
@@ -16,11 +16,8 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriendlyString;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.content.ApexEnvironment;
@@ -30,7 +27,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.BackgroundThread;
import com.android.safetycenter.ApiLock;
@@ -48,6 +45,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -66,7 +64,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterIssueDismissalRepository {
@@ -130,11 +127,7 @@ final class SafetyCenterIssueDismissalRepository {
Duration timeSinceLastDismissal = Duration.between(dismissedAt, Instant.now());
boolean isTimeToResurface = timeSinceLastDismissal.compareTo(delay) >= 0;
- if (isTimeToResurface) {
- return false;
- }
-
- return true;
+ return !isTimeToResurface;
}
/**
@@ -342,7 +335,7 @@ final class SafetyCenterIssueDismissalRepository {
* and all following calls won't have any effect.
*/
void resurfaceHiddenIssueAfterPeriod(SafetyCenterIssueKey safetyCenterIssueKey) {
- IssueData issueData = getOrWarn(safetyCenterIssueKey, "resurfaceIssueAfterPeriod");
+ IssueData issueData = getOrWarn(safetyCenterIssueKey, "resurfacing hidden issue");
if (issueData == null) {
return;
}
@@ -439,13 +432,22 @@ final class SafetyCenterIssueDismissalRepository {
fout.flush();
try {
Files.copy(issueDismissalRepositoryFile.toPath(), new FileOutputStream(fd));
+ fout.println();
+ } catch (NoSuchFileException e) {
+ fout.println("<No File> (equivalent to empty issue list)");
} catch (IOException e) {
- // TODO(b/266202404)
- e.printStackTrace(fout);
+ printError(e, fout);
}
fout.println();
}
+ // We want to dump the stack trace on a specific PrintWriter here, this is a false positive as
+ // the warning does not consider the overload that takes a PrintWriter as an argument (yet).
+ @SuppressWarnings("CatchAndPrintStackTrace")
+ private void printError(Throwable error, PrintWriter fout) {
+ error.printStackTrace(fout);
+ }
+
@Nullable
private IssueData getOrWarn(SafetyCenterIssueKey issueKey, String reason) {
IssueData issueData = mIssues.get(issueKey);
@@ -492,9 +494,9 @@ final class SafetyCenterIssueDismissalRepository {
try {
persistedSafetyCenterIssues =
SafetyCenterIssuesPersistence.read(getIssueDismissalRepositoryFile());
- Log.i(TAG, "Safety Center persisted issues read successfully");
+ Log.d(TAG, "Safety Center persisted issues read successfully");
} catch (PersistenceException e) {
- Log.e(TAG, "Cannot read Safety Center persisted issues", e);
+ Log.w(TAG, "Cannot read Safety Center persisted issues", e);
}
load(persistedSafetyCenterIssues);
diff --git a/service/java/com/android/safetycenter/data/SafetyCenterIssueRepository.java b/service/java/com/android/safetycenter/data/SafetyCenterIssueRepository.java
index 566c28c1e..2e6f707a3 100644
--- a/service/java/com/android/safetycenter/data/SafetyCenterIssueRepository.java
+++ b/service/java/com/android/safetycenter/data/SafetyCenterIssueRepository.java
@@ -16,8 +16,6 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.safetycenter.data.SafetyCenterIssueDeduplicator.DeduplicationInfo;
import static java.util.Collections.emptyList;
@@ -32,8 +30,6 @@ import android.safetycenter.config.SafetySource;
import android.safetycenter.config.SafetySourcesGroup;
import android.util.SparseArray;
-import androidx.annotation.RequiresApi;
-
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.UserUtils;
import com.android.safetycenter.SafetyCenterConfigReader;
@@ -56,7 +52,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>Responsible for generating lists of issues and deduplication of issues.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetyCenterIssueRepository {
@@ -92,19 +87,6 @@ final class SafetyCenterIssueRepository {
* Updates the class as per the current state of issues. Should be called after any state update
* that can affect issues.
*/
- void updateIssues(UserProfileGroup userProfileGroup) {
- updateIssues(userProfileGroup.getProfileParentUserId(), /* isManagedProfile= */ false);
-
- int[] managedProfileUserIds = userProfileGroup.getManagedProfilesUserIds();
- for (int i = 0; i < managedProfileUserIds.length; i++) {
- updateIssues(managedProfileUserIds[i], /* isManagedProfile= */ true);
- }
- }
-
- /**
- * Updates the class as per the current state of issues. Should be called after any state update
- * that can affect issues.
- */
void updateIssues(@UserIdInt int userId) {
updateIssues(userId, UserUtils.isManagedProfile(userId, mContext));
}
diff --git a/service/java/com/android/safetycenter/data/SafetyEventFix.java b/service/java/com/android/safetycenter/data/SafetyEventFix.java
new file mode 100644
index 000000000..4050eddfb
--- /dev/null
+++ b/service/java/com/android/safetycenter/data/SafetyEventFix.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.data;
+
+import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED;
+import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED;
+
+import android.annotation.UserIdInt;
+import android.safetycenter.SafetyEvent;
+import android.safetycenter.SafetySourceData;
+import android.safetycenter.SafetySourceIssue;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
+
+import java.util.List;
+
+/**
+ * Works around sources sending unexpected {@link SafetyEvent}s by optionally replacing them using
+ * heuristics based on the incoming {@link SafetySourceData} and Safety Center's current state.
+ *
+ * @hide
+ */
+public final class SafetyEventFix {
+
+ private static final String TAG = "SafetyEventFix";
+
+ private SafetyEventFix() {}
+
+ /**
+ * Optionally returns a new {@link SafetyEvent} if heuristics indicate that the one provided by
+ * the source is inappropriate, otherwise returns the source-provided event unchanged.
+ *
+ * <p>If the incoming event has type {@link SafetyEvent#SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED}
+ * but the {@link SafetySourceData} no longer includes an issue, for which Safety Center has a
+ * record of an in-flight, resolving action, then the event will be exchanged for a new one of
+ * type {@link SafetyEvent#SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED}.
+ */
+ public static SafetyEvent maybeOverrideSafetyEvent(
+ SafetyCenterDataManager dataManager,
+ String safetySourceId,
+ @Nullable SafetySourceData safetySourceData,
+ SafetyEvent safetyEvent,
+ @UserIdInt int userId) {
+ if (safetySourceData == null
+ || safetyEvent.getType() != SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED) {
+ return safetyEvent;
+ }
+
+ ArraySet<SafetyCenterIssueActionId> possiblySuccessfulActions =
+ dataManager.getInFlightActions(safetySourceId, userId);
+
+ if (possiblySuccessfulActions.isEmpty()) {
+ return safetyEvent;
+ }
+
+ // Discard any actions for which the issue is still present in the latest source data, they
+ // cannot have been resolved successfully!
+ ArraySet<String> presentSourceIssueIds = getSourceIssueIds(safetySourceData);
+ for (int i = possiblySuccessfulActions.size() - 1; i >= 0; i--) {
+ String sourceIssueId =
+ possiblySuccessfulActions
+ .valueAt(i)
+ .getSafetyCenterIssueKey()
+ .getSafetySourceIssueId();
+ if (presentSourceIssueIds.contains(sourceIssueId)) {
+ possiblySuccessfulActions.removeAt(i);
+ }
+ }
+
+ if (possiblySuccessfulActions.isEmpty()) {
+ return safetyEvent;
+ }
+
+ if (possiblySuccessfulActions.size() > 1) {
+ Log.i(TAG, "Multiple actions resolved, not overriding " + safetyEvent);
+ return safetyEvent;
+ }
+
+ SafetyCenterIssueActionId successfulAction = possiblySuccessfulActions.valueAt(0);
+ SafetyEvent replacement = newActionSucceededEvent(successfulAction);
+ Log.i(TAG, "Replacing incoming " + safetyEvent + " with " + replacement);
+ return replacement;
+ }
+
+ private static ArraySet<String> getSourceIssueIds(SafetySourceData safetySourceData) {
+ List<SafetySourceIssue> issues = safetySourceData.getIssues();
+ ArraySet<String> issueIds = new ArraySet<>(issues.size());
+ for (int i = 0; i < issues.size(); i++) {
+ issueIds.add(issues.get(i).getId());
+ }
+ return issueIds;
+ }
+
+ private static SafetyEvent newActionSucceededEvent(SafetyCenterIssueActionId actionId) {
+ return new SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED)
+ .setSafetySourceIssueId(actionId.getSafetyCenterIssueKey().getSafetySourceIssueId())
+ .setSafetySourceIssueActionId(actionId.getSafetySourceIssueActionId())
+ .build();
+ }
+}
diff --git a/service/java/com/android/safetycenter/data/SafetySourceDataRepository.java b/service/java/com/android/safetycenter/data/SafetySourceDataRepository.java
index b47f7925e..cdb8709d6 100644
--- a/service/java/com/android/safetycenter/data/SafetySourceDataRepository.java
+++ b/service/java/com/android/safetycenter/data/SafetySourceDataRepository.java
@@ -16,18 +16,14 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__DATA_PROVIDED;
import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__NO_DATA_PROVIDED;
import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__REFRESH_TIMEOUT;
import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_CLEARED;
import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_ERROR;
-import android.annotation.Nullable;
import android.annotation.UptimeMillisLong;
import android.annotation.UserIdInt;
-import android.content.Context;
import android.os.SystemClock;
import android.safetycenter.SafetyCenterData;
import android.safetycenter.SafetyEvent;
@@ -38,7 +34,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.safetycenter.SafetySourceKey;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
@@ -57,7 +53,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetySourceDataRepository {
@@ -68,24 +63,20 @@ final class SafetySourceDataRepository {
private final ArrayMap<SafetySourceKey, Long> mSafetySourceLastUpdated = new ArrayMap<>();
private final ArrayMap<SafetySourceKey, Integer> mSourceStates = new ArrayMap<>();
- private final Context mContext;
private final SafetyCenterInFlightIssueActionRepository
mSafetyCenterInFlightIssueActionRepository;
private final SafetyCenterIssueDismissalRepository mSafetyCenterIssueDismissalRepository;
SafetySourceDataRepository(
- Context context,
SafetyCenterInFlightIssueActionRepository safetyCenterInFlightIssueActionRepository,
SafetyCenterIssueDismissalRepository safetyCenterIssueDismissalRepository) {
- mContext = context;
mSafetyCenterInFlightIssueActionRepository = safetyCenterInFlightIssueActionRepository;
mSafetyCenterIssueDismissalRepository = safetyCenterIssueDismissalRepository;
}
/**
- * Sets the latest {@link SafetySourceData} for the given {@code safetySourceId}, {@link
- * SafetyEvent}, {@code packageName} and {@code userId}, and returns {@code true} if this caused
- * any changes which would alter {@link SafetyCenterData}.
+ * Sets the latest {@link SafetySourceData} for the given {@link SafetySourceKey}, and returns
+ * {@code true} if this caused any changes which would alter {@link SafetyCenterData}.
*
* <p>This method does not perform any validation, {@link
* SafetyCenterDataManager#setSafetySourceData(SafetySourceData, String, SafetyEvent, String,
@@ -98,22 +89,16 @@ final class SafetySourceDataRepository {
* <p>This method may modify the {@link SafetyCenterIssueDismissalRepository}.
*/
boolean setSafetySourceData(
- @Nullable SafetySourceData safetySourceData,
- String safetySourceId,
- @UserIdInt int userId) {
- SafetySourceKey key = SafetySourceKey.of(safetySourceId, userId);
- safetySourceData =
- AndroidLockScreenFix.maybeOverrideSafetySourceData(
- mContext, safetySourceId, safetySourceData);
-
- boolean sourceDataDiffers = !Objects.equals(safetySourceData, mSafetySourceData.get(key));
- boolean removedSourceError = mSafetySourceErrors.remove(key);
+ SafetySourceKey safetySourceKey, @Nullable SafetySourceData safetySourceData) {
+ boolean sourceDataDiffers =
+ !Objects.equals(safetySourceData, mSafetySourceData.get(safetySourceKey));
+ boolean removedSourceError = mSafetySourceErrors.remove(safetySourceKey);
if (sourceDataDiffers) {
- setSafetySourceDataInternal(key, safetySourceData);
+ setSafetySourceDataInternal(safetySourceKey, safetySourceData);
}
- setLastUpdatedNow(key);
+ setLastUpdatedNow(safetySourceKey);
return sourceDataDiffers || removedSourceError;
}
@@ -155,19 +140,33 @@ final class SafetySourceDataRepository {
}
/**
- * Reports the given {@link SafetySourceErrorDetails} for the given {@code safetySourceId} and
- * {@code userId}, and returns {@code true} if this changed the repository's data.
+ * Returns whether the repository has the given {@link SafetySourceData} for the given {@link
+ * SafetySourceKey}.
+ */
+ boolean sourceHasData(
+ SafetySourceKey safetySourceKey, @Nullable SafetySourceData safetySourceData) {
+ if (mSafetySourceErrors.contains(safetySourceKey)) {
+ // Any error will cause the SafetySourceData to be discarded in favor of an error
+ // message, so it can't possibly match the SafetySourceData passed in parameter.
+ return false;
+ }
+ return Objects.equals(safetySourceData, mSafetySourceData.get(safetySourceKey));
+ }
+
+ /**
+ * Reports the given {@link SafetySourceErrorDetails} for the given {@link SafetySourceKey}, and
+ * returns {@code true} if this changed the repository's data.
*
* <p>This method does not perform any validation, {@link
* SafetyCenterDataManager#reportSafetySourceError(SafetySourceErrorDetails, String, String,
* int)} should be called wherever validation is required.
*/
boolean reportSafetySourceError(
- SafetySourceErrorDetails safetySourceErrorDetails,
- String safetySourceId,
- @UserIdInt int userId) {
+ SafetySourceKey safetySourceKey, SafetySourceErrorDetails safetySourceErrorDetails) {
SafetyEvent safetyEvent = safetySourceErrorDetails.getSafetyEvent();
- Log.w(TAG, "Error reported from source: " + safetySourceId + ", for event: " + safetyEvent);
+ Log.w(
+ TAG,
+ "Error reported from source: " + safetySourceKey + ", for event: " + safetyEvent);
int safetyEventType = safetyEvent.getType();
if (safetyEventType == SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
@@ -175,9 +174,9 @@ final class SafetySourceDataRepository {
return false;
}
- SafetySourceKey sourceKey = SafetySourceKey.of(safetySourceId, userId);
- mSourceStates.put(sourceKey, SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_ERROR);
- return setSafetySourceError(sourceKey);
+ mSourceStates.put(
+ safetySourceKey, SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_ERROR);
+ return setSafetySourceError(safetySourceKey);
}
/**
@@ -339,9 +338,9 @@ final class SafetySourceDataRepository {
SafetySourceKey key = mSafetySourceErrors.valueAt(i);
fout.println("\t[" + i + "] " + key);
}
+ fout.println();
dumpArrayMap(fout, mSafetySourceLastUpdated, "LAST UPDATED");
dumpArrayMap(fout, mSourceStates, "SOURCE STATES");
- fout.println();
}
private static <K, V> void dumpArrayMap(PrintWriter fout, ArrayMap<K, V> map, String label) {
@@ -350,5 +349,6 @@ final class SafetySourceDataRepository {
for (int i = 0; i < count; i++) {
fout.println("\t[" + i + "] " + map.keyAt(i) + " -> " + map.valueAt(i));
}
+ fout.println();
}
}
diff --git a/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java b/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java
index cc265d7f9..7355035b0 100644
--- a/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java
+++ b/service/java/com/android/safetycenter/data/SafetySourceDataValidator.java
@@ -16,9 +16,6 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -29,7 +26,7 @@ import android.safetycenter.SafetySourceStatus;
import android.safetycenter.config.SafetySource;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.UserUtils;
@@ -48,11 +45,10 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* <p>This class isn't thread safe. Thread safety must be handled by the caller.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetySourceDataValidator {
- private static final String TAG = "SafetySourceDataValidator";
+ private static final String TAG = "SafetySourceDataValidat";
private final Context mContext;
private final SafetyCenterConfigReader mSafetyCenterConfigReader;
@@ -74,9 +70,12 @@ final class SafetySourceDataValidator {
*
* @param safetySourceData being set, or {@code null} if retrieving or clearing data, or
* reporting an error
+ * @param callerCanAccessAnySource whether we should allow the caller to access any source, or
+ * restrict them to their own {@code packageName}
*/
boolean validateRequest(
@Nullable SafetySourceData safetySourceData,
+ boolean callerCanAccessAnySource,
String safetySourceId,
String packageName,
@UserIdInt int userId) {
@@ -87,7 +86,9 @@ final class SafetySourceDataValidator {
}
SafetySource safetySource = externalSafetySource.getSafetySource();
- validateCallingPackage(safetySource, packageName, safetySourceId);
+ if (!callerCanAccessAnySource) {
+ validateCallingPackage(safetySource, packageName, safetySourceId);
+ }
if (UserUtils.isManagedProfile(userId, mContext)
&& !SafetySources.supportsManagedProfiles(safetySource)) {
@@ -97,8 +98,8 @@ final class SafetySourceDataValidator {
boolean retrievingOrClearingData = safetySourceData == null;
if (retrievingOrClearingData) {
- return mSafetyCenterConfigReader.isExternalSafetySourceActive(
- safetySourceId, packageName);
+ return isExternalSafetySourceActive(
+ callerCanAccessAnySource, safetySourceId, packageName);
}
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
@@ -164,7 +165,20 @@ final class SafetySourceDataValidator {
}
}
- return mSafetyCenterConfigReader.isExternalSafetySourceActive(safetySourceId, packageName);
+ return isExternalSafetySourceActive(callerCanAccessAnySource, safetySourceId, packageName);
+ }
+
+ private boolean isExternalSafetySourceActive(
+ boolean callerCanAccessAnySource, String safetySourceId, String callerPackageName) {
+ boolean isActive =
+ mSafetyCenterConfigReader.isExternalSafetySourceActive(
+ safetySourceId, callerCanAccessAnySource ? null : callerPackageName);
+ if (!isActive) {
+ Log.i(
+ TAG,
+ "Call ignored as safety source " + safetySourceId + " is not currently active");
+ }
+ return isActive;
}
private void validateCallingPackage(
@@ -192,13 +206,13 @@ final class SafetySourceDataValidator {
&& !checkCerts(
packageName,
SafetyCenterFlags.getAdditionalAllowedPackageCerts(packageName))) {
- Log.e(
+ Log.w(
TAG,
- "Package "
+ "Package: "
+ packageName
- + " for source "
+ + ", for source: "
+ safetySourceId
- + " signed with invalid signature");
+ + " is signed with invalid signature");
throw new IllegalArgumentException("Invalid signature for package " + packageName);
}
}
@@ -210,7 +224,7 @@ final class SafetySourceDataValidator {
byte[] certificate = new Signature(certHash).toByteArray();
if (mPackageManager.hasSigningCertificate(
packageName, certificate, PackageManager.CERT_INPUT_SHA256)) {
- Log.d(TAG, "Package " + packageName + " has expected signature");
+ Log.v(TAG, "Package: " + packageName + " has expected signature");
hasMatchingCert = true;
}
} catch (IllegalArgumentException e) {
diff --git a/service/java/com/android/safetycenter/data/SafetySourceStateCollectedLogger.java b/service/java/com/android/safetycenter/data/SafetySourceStateCollectedLogger.java
index b6bf280ae..e73459598 100644
--- a/service/java/com/android/safetycenter/data/SafetySourceStateCollectedLogger.java
+++ b/service/java/com/android/safetycenter/data/SafetySourceStateCollectedLogger.java
@@ -16,10 +16,7 @@
package com.android.safetycenter.data;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import android.annotation.ElapsedRealtimeLong;
-import android.annotation.Nullable;
import android.content.Context;
import android.safetycenter.SafetyCenterManager;
import android.safetycenter.SafetyEvent;
@@ -27,7 +24,7 @@ import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.safetycenter.SafetySourceStatus;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.UserUtils;
import com.android.safetycenter.SafetySourceIssueInfo;
@@ -44,7 +41,6 @@ import javax.annotation.concurrent.NotThreadSafe;
* Collates information from various data-related classes and uses that information to log {@code
* SafetySourceStateCollected} atoms.
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
final class SafetySourceStateCollectedLogger {
@@ -132,10 +128,11 @@ final class SafetySourceStateCollectedLogger {
}
}
+ Integer severityLevel = maxSeverityLevel > Integer.MIN_VALUE ? maxSeverityLevel : null;
SafetyCenterStatsdLogger.writeSafetySourceStateCollected(
sourceKey.getSourceId(),
isManagedProfile,
- maxSeverityLevel > Integer.MIN_VALUE ? maxSeverityLevel : null,
+ severityLevel,
openIssuesCount,
dismissedIssuesCount,
getDuplicateCount(sourceKey),
diff --git a/service/java/com/android/safetycenter/data/package-info.java b/service/java/com/android/safetycenter/data/package-info.java
index 597847505..e82755370 100644
--- a/service/java/com/android/safetycenter/data/package-info.java
+++ b/service/java/com/android/safetycenter/data/package-info.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
@NonNullByDefault
+@RequiresTiramisuByDefault
package com.android.safetycenter.data;
import com.android.safetycenter.annotations.NonNullByDefault;
+import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/logging/SafetyCenterPullAtomCallback.java b/service/java/com/android/safetycenter/logging/SafetyCenterPullAtomCallback.java
index d9514f56e..168d73a0f 100644
--- a/service/java/com/android/safetycenter/logging/SafetyCenterPullAtomCallback.java
+++ b/service/java/com/android/safetycenter/logging/SafetyCenterPullAtomCallback.java
@@ -16,8 +16,6 @@
package com.android.safetycenter.logging;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.permission.PermissionStatsLog.SAFETY_STATE;
import android.annotation.UserIdInt;
@@ -30,8 +28,6 @@ import android.safetycenter.config.SafetySourcesGroup;
import android.util.Log;
import android.util.StatsEvent;
-import androidx.annotation.RequiresApi;
-
import com.android.internal.annotations.GuardedBy;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.PermissionStatsLog;
@@ -56,7 +52,6 @@ import java.util.List;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetyCenterPullAtomCallback implements StatsPullAtomCallback {
private static final String TAG = "SafetyCenterPullAtom";
@@ -93,17 +88,17 @@ public final class SafetyCenterPullAtomCallback implements StatsPullAtomCallback
return StatsManager.PULL_SKIP;
}
if (!SafetyCenterFlags.getSafetyCenterEnabled()) {
- Log.w(TAG, "Attempt to pull SAFETY_STATE, but Safety Center is disabled");
+ Log.i(TAG, "Attempt to pull SAFETY_STATE, but Safety Center is disabled");
return StatsManager.PULL_SKIP;
}
List<UserProfileGroup> userProfileGroups =
UserProfileGroup.getAllUserProfileGroups(mContext);
synchronized (mApiLock) {
if (!SafetyCenterFlags.getAllowStatsdLogging()) {
- Log.w(TAG, "Skipping pulling and writing atoms due to logging being disabled");
+ Log.i(TAG, "Skipping pulling and writing atoms due to logging being disabled");
return StatsManager.PULL_SKIP;
}
- Log.i(TAG, "Pulling and writing atoms…");
+ Log.d(TAG, "Pulling and writing atoms…");
for (int i = 0; i < userProfileGroups.size(); i++) {
UserProfileGroup userProfileGroup = userProfileGroups.get(i);
List<SafetySourcesGroup> loggableGroups =
@@ -111,8 +106,8 @@ public final class SafetyCenterPullAtomCallback implements StatsPullAtomCallback
statsEvents.add(
createOverallSafetyStateAtomLocked(userProfileGroup, loggableGroups));
// The SAFETY_SOURCE_STATE_COLLECTED atoms are written instead of being pulled,
- // they do not support pull but we want to collect them at the same time as
- // the above pulled atom.
+ // as they do not support pull. We still want to collect them at the same time as
+ // the above pulled atom, which is why they're written here.
writeSafetySourceStateCollectedAtomsLocked(userProfileGroup, loggableGroups);
}
}
@@ -165,7 +160,8 @@ public final class SafetyCenterPullAtomCallback implements StatsPullAtomCallback
int[] managedIds = userProfileGroup.getManagedRunningProfilesUserIds();
for (int k = 0; k < managedIds.length; k++) {
- writeSafetySourceStateCollectedAtomLocked(loggableSource, managedIds[k], true);
+ writeSafetySourceStateCollectedAtomLocked(
+ loggableSource, managedIds[k], /* isUserManaged= */ true);
}
}
}
diff --git a/service/java/com/android/safetycenter/logging/SafetyCenterStatsdLogger.java b/service/java/com/android/safetycenter/logging/SafetyCenterStatsdLogger.java
index 8ca662d27..710c3f7ac 100644
--- a/service/java/com/android/safetycenter/logging/SafetyCenterStatsdLogger.java
+++ b/service/java/com/android/safetycenter/logging/SafetyCenterStatsdLogger.java
@@ -16,8 +16,6 @@
package com.android.safetycenter.logging;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED;
import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_PRIMARY_ACTION_CLICKED;
import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_SECONDARY_ACTION_CLICKED;
@@ -74,7 +72,6 @@ import static com.android.permission.PermissionStatsLog.SAFETY_STATE__OVERALL_SE
import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.safetycenter.SafetyCenterManager;
import android.safetycenter.SafetyCenterManager.RefreshRequestType;
import android.safetycenter.SafetyCenterStatus;
@@ -83,7 +80,7 @@ import android.safetycenter.SafetySourceData;
import android.util.Log;
import android.util.StatsEvent;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.PermissionStatsLog;
import com.android.safetycenter.SafetyCenterFlags;
@@ -101,7 +98,6 @@ import java.time.Duration;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetyCenterStatsdLogger {
private static final String TAG = "SafetyCenterStatsdLog";
diff --git a/service/java/com/android/safetycenter/logging/package-info.java b/service/java/com/android/safetycenter/logging/package-info.java
index dcc1828b4..47575f2d9 100644
--- a/service/java/com/android/safetycenter/logging/package-info.java
+++ b/service/java/com/android/safetycenter/logging/package-info.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
@NonNullByDefault
+@RequiresTiramisuByDefault
package com.android.safetycenter.logging;
import com.android.safetycenter.annotations.NonNullByDefault;
+import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationChannels.java b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationChannels.java
index 5308cdae8..ccd2bfabc 100644
--- a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationChannels.java
+++ b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationChannels.java
@@ -16,11 +16,6 @@
package com.android.safetycenter.notifications;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
@@ -31,10 +26,11 @@ import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.permission.util.UserUtils;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.SafetyCenterFlags;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.util.List;
@@ -43,7 +39,6 @@ import java.util.List;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetyCenterNotificationChannels {
private static final String TAG = "SafetyCenterNC";
@@ -53,11 +48,10 @@ public final class SafetyCenterNotificationChannels {
private static final String CHANNEL_ID_RECOMMENDATION = "safety_center_recommendation";
private static final String CHANNEL_ID_CRITICAL_WARNING = "safety_center_critical_warning";
- private final SafetyCenterResourcesContext mResourcesContext;
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
- public SafetyCenterNotificationChannels(
- SafetyCenterResourcesContext safetyCenterResourceContext) {
- mResourcesContext = safetyCenterResourceContext;
+ public SafetyCenterNotificationChannels(SafetyCenterResourcesApk safetyCenterResourcesApk) {
+ mSafetyCenterResourcesApk = safetyCenterResourcesApk;
}
/** Returns a {@link NotificationManager} which will send notifications to the given user. */
@@ -70,7 +64,10 @@ public final class SafetyCenterNotificationChannels {
? contextAsUser.getSystemService(NotificationManager.class)
: null;
if (notificationManager == null) {
- Log.w(TAG, "Could not retrieve NotificationManager for user " + userHandle);
+ Log.w(
+ TAG,
+ "Could not retrieve NotificationManager for user id: "
+ + userHandle.getIdentifier());
}
return notificationManager;
}
@@ -80,9 +77,9 @@ public final class SafetyCenterNotificationChannels {
// This call requires the INTERACT_ACROSS_USERS permission.
final long callingId = Binder.clearCallingIdentity();
try {
- return baseContext.createContextAsUser(userHandle, 0);
+ return baseContext.createContextAsUser(userHandle, /* flags= */ 0);
} catch (RuntimeException e) {
- Log.w(TAG, "Could not create Context as user " + userHandle, e);
+ Log.w(TAG, "Could not create Context as user id: " + userHandle.getIdentifier(), e);
return null;
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -106,10 +103,18 @@ public final class SafetyCenterNotificationChannels {
/**
* Creates all Safety Center {@link NotificationChannel}s instances and their group, for all
- * current users, dropping any calling identity so those channels can be unblockable. Throws a
- * {@link RuntimeException} if any channel is malformed and could not be created.
+ * current users, dropping any calling identity so those channels can be unblockable.
*/
public void createAllChannelsForAllUsers(Context context) {
+ if (!SafetyCenterFlags.getNotificationsEnabled()) {
+ // TODO(b/284271124): Decide what to do with existing channels if flag gets toggled.
+ Log.i(
+ TAG,
+ "Not creating notification channels because Safety Center notifications are"
+ + " disabled");
+ return;
+ }
+
List<UserHandle> users = UserUtils.getUserHandles(context);
for (int i = 0; i < users.size(); i++) {
createAllChannelsForUser(context, users.get(i));
@@ -119,31 +124,54 @@ public final class SafetyCenterNotificationChannels {
/**
* Creates all Safety Center {@link NotificationChannel}s instances and their group for the
* given {@link UserHandle}, dropping any calling identity so those channels can be unblockable.
- * Throws a {@link RuntimeException} if any channel is malformed and could not be created.
*/
public void createAllChannelsForUser(Context context, UserHandle user) {
+ if (!SafetyCenterFlags.getNotificationsEnabled()) {
+ // TODO(b/284271124): Decide what to do with existing channels if flag gets toggled.
+ Log.i(
+ TAG,
+ "Not creating notification channels because Safety Center notifications are"
+ + " disabled");
+ return;
+ }
+
+ NotificationManager notificationManager = getNotificationManagerForUser(context, user);
+ if (notificationManager == null) {
+ return;
+ }
+
try {
- NotificationManager notificationManager =
- requireNonNull(getNotificationManagerForUser(context, user));
createAllChannelsWithoutCallingIdentity(notificationManager);
} catch (RuntimeException e) {
- Log.w(TAG, "Error creating notification channels for user " + user.getIdentifier(), e);
+ Log.w(
+ TAG,
+ "Error creating notification channels for user id: " + user.getIdentifier(),
+ e);
}
}
@Nullable
private String getChannelIdForIssue(SafetySourceIssue issue) {
- switch (issue.getSeverityLevel()) {
+ int issueSeverityLevel = issue.getSeverityLevel();
+ switch (issueSeverityLevel) {
case SafetySourceData.SEVERITY_LEVEL_INFORMATION:
return CHANNEL_ID_INFORMATION;
case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION:
return CHANNEL_ID_RECOMMENDATION;
case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING:
return CHANNEL_ID_CRITICAL_WARNING;
- default:
- Log.w(TAG, "No applicable notification channel for issue " + issue);
+ case SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED:
+ Log.w(TAG, "SafetySourceData.SeverityLevel is unspecified for issue: " + issue);
return null;
}
+
+ Log.w(
+ TAG,
+ "Unexpected SafetySourceData.SeverityLevel: "
+ + issueSeverityLevel
+ + ", for issue: "
+ + issue);
+ return null;
}
/**
@@ -153,7 +181,8 @@ public final class SafetyCenterNotificationChannels {
* created.
*/
private void createAllChannelsWithoutCallingIdentity(NotificationManager notificationManager) {
- // Clearing calling identity to be able to make unblockable system notification channels
+ // Clearing calling identity to be able to make unblockable system notification channels and
+ // call this for other users with the INTERACT_ACROSS_USERS permission.
final long callingId = Binder.clearCallingIdentity();
try {
notificationManager.createNotificationChannelGroup(getChannelGroupDefinition());
@@ -165,6 +194,17 @@ public final class SafetyCenterNotificationChannels {
}
}
+ private void clearAllChannelsWithoutCallingIdentity(NotificationManager notificationManager) {
+ // Clearing calling identity to do this for other users with the INTERACT_ACROSS_USERS
+ // permission.
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ notificationManager.deleteNotificationChannelGroup(CHANNEL_GROUP_ID);
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
private NotificationChannelGroup getChannelGroupDefinition() {
return new NotificationChannelGroup(
CHANNEL_GROUP_ID, getString("notification_channel_group_name"));
@@ -204,6 +244,6 @@ public final class SafetyCenterNotificationChannels {
}
private String getString(String name) {
- return mResourcesContext.getStringByName(name);
+ return mSafetyCenterResourcesApk.getStringByName(name);
}
}
diff --git a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
index a8da70cf0..84001f249 100644
--- a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
+++ b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationFactory.java
@@ -16,7 +16,6 @@
package com.android.safetycenter.notifications;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID;
import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID;
import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_HANDLE;
@@ -24,7 +23,6 @@ import static android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_
import static com.android.safetycenter.notifications.SafetyCenterNotificationChannels.getContextAsUser;
import android.annotation.ColorInt;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -32,7 +30,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.UserHandle;
@@ -40,14 +37,14 @@ import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.text.TextUtils;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.safetycenter.PendingIntentFactory;
import com.android.safetycenter.internaldata.SafetyCenterIds;
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId;
import com.android.safetycenter.internaldata.SafetyCenterIssueKey;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.time.Duration;
import java.util.List;
@@ -56,24 +53,22 @@ import java.util.List;
* Factory that builds {@link Notification} objects from {@link SafetySourceIssue} instances with
* appropriate {@link PendingIntent}s for click and dismiss callbacks.
*/
-@RequiresApi(TIRAMISU)
final class SafetyCenterNotificationFactory {
- private static final String TAG = "SafetyCenterNF";
private static final int OPEN_SAFETY_CENTER_REQUEST_CODE = 1221;
private static final Duration SUCCESS_NOTIFICATION_TIMEOUT = Duration.ofSeconds(10);
private final Context mContext;
private final SafetyCenterNotificationChannels mNotificationChannels;
- private final SafetyCenterResourcesContext mResourcesContext;
+ private final SafetyCenterResourcesApk mSafetyCenterResourcesApk;
SafetyCenterNotificationFactory(
Context context,
SafetyCenterNotificationChannels notificationChannels,
- SafetyCenterResourcesContext resourcesContext) {
+ SafetyCenterResourcesApk safetyCenterResourcesApk) {
mContext = context;
mNotificationChannels = notificationChannels;
- mResourcesContext = resourcesContext;
+ mSafetyCenterResourcesApk = safetyCenterResourcesApk;
}
/**
@@ -89,6 +84,10 @@ final class SafetyCenterNotificationFactory {
SafetySourceIssue issue,
SafetySourceIssue.Action action,
@UserIdInt int userId) {
+ if (action.getSuccessMessage() == null) {
+ return null;
+ }
+
String channelId = mNotificationChannels.getCreatedChannelId(notificationManager, issue);
if (channelId == null) {
return null;
@@ -107,7 +106,8 @@ final class SafetyCenterNotificationFactory {
.setContentTitle(action.getSuccessMessage())
.setShowWhen(true)
.setTimeoutAfter(SUCCESS_NOTIFICATION_TIMEOUT.toMillis())
- .setContentIntent(contentIntent);
+ .setContentIntent(contentIntent)
+ .setAutoCancel(true);
Integer color = getNotificationColor(SafetySourceData.SEVERITY_LEVEL_INFORMATION);
if (color != null) {
@@ -175,6 +175,10 @@ final class SafetyCenterNotificationFactory {
builder.addAction(notificationAction);
}
+ if (issue.getSeverityLevel() == SafetySourceData.SEVERITY_LEVEL_INFORMATION) {
+ builder.setAutoCancel(true);
+ }
+
return builder.build();
}
@@ -231,7 +235,7 @@ final class SafetyCenterNotificationFactory {
if (severityLevel == SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING) {
iconResName = "ic_notification_badge_critical";
}
- Icon icon = mResourcesContext.getIconByDrawableName(iconResName);
+ Icon icon = mSafetyCenterResourcesApk.getIconByDrawableName(iconResName);
if (icon == null) {
// In case it was impossible to fetch the above drawable for any reason use this
// fallback which should be present on all Android devices:
@@ -247,12 +251,13 @@ final class SafetyCenterNotificationFactory {
if (severityLevel == SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING) {
colorResName = "notification_tint_critical";
}
- return mResourcesContext.getColorByName(colorResName);
+ return mSafetyCenterResourcesApk.getColorByName(colorResName);
}
private Bundle getNotificationExtras() {
Bundle extras = new Bundle();
- String appName = mResourcesContext.getStringByName("notification_channel_group_name");
+ String appName =
+ mSafetyCenterResourcesApk.getStringByName("notification_channel_group_name");
if (!TextUtils.isEmpty(appName)) {
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);
}
@@ -262,7 +267,9 @@ final class SafetyCenterNotificationFactory {
private Notification.Action toNotificationAction(
SafetyCenterIssueKey issueKey, SafetySourceIssue.Action issueAction) {
PendingIntent pendingIntent = getPendingIntentForAction(issueKey, issueAction);
- return new Notification.Action.Builder(null, issueAction.getLabel(), pendingIntent).build();
+ return new Notification.Action.Builder(
+ /* icon= */ null, issueAction.getLabel(), pendingIntent)
+ .build();
}
private PendingIntent getPendingIntentForAction(
@@ -270,7 +277,7 @@ final class SafetyCenterNotificationFactory {
if (issueAction.willResolve()) {
return getReceiverPendingIntentForResolvingAction(issueKey, issueAction);
} else {
- return getDirectPendingIntentForNonResolvingAction(issueKey, issueAction);
+ return getDirectPendingIntentForNonResolvingAction(issueAction);
}
}
@@ -291,12 +298,7 @@ final class SafetyCenterNotificationFactory {
}
private PendingIntent getDirectPendingIntentForNonResolvingAction(
- SafetyCenterIssueKey issueKey, SafetySourceIssue.Action issueAction) {
+ SafetySourceIssue.Action issueAction) {
return issueAction.getPendingIntent();
}
-
- private static boolean isDarkTheme(Context context) {
- return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
- }
}
diff --git a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationReceiver.java b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationReceiver.java
index 0b4ac5ab3..ed0e95177 100644
--- a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationReceiver.java
+++ b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationReceiver.java
@@ -16,9 +16,6 @@
package com.android.safetycenter.notifications;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
-
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -27,7 +24,7 @@ import android.content.IntentFilter;
import android.safetycenter.SafetySourceIssue;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.GuardedBy;
import com.android.permission.util.UserUtils;
@@ -36,6 +33,7 @@ import com.android.safetycenter.PendingIntentFactory;
import com.android.safetycenter.SafetyCenterDataChangeNotifier;
import com.android.safetycenter.SafetyCenterFlags;
import com.android.safetycenter.SafetyCenterService;
+import com.android.safetycenter.SafetySourceIssues;
import com.android.safetycenter.UserProfileGroup;
import com.android.safetycenter.data.SafetyCenterDataManager;
import com.android.safetycenter.internaldata.SafetyCenterIds;
@@ -54,7 +52,6 @@ import com.android.safetycenter.logging.SafetyCenterStatsdLogger;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
public final class SafetyCenterNotificationReceiver extends BroadcastReceiver {
private static final String TAG = "SafetyCenterNR";
@@ -120,13 +117,13 @@ public final class SafetyCenterNotificationReceiver extends BroadcastReceiver {
private static SafetyCenterIssueActionId getIssueActionIdExtra(Intent intent) {
String issueActionIdString = intent.getStringExtra(EXTRA_ISSUE_ACTION_ID);
if (issueActionIdString == null) {
- Log.w(TAG, "Received notification action broadcast with null issue action ID");
+ Log.w(TAG, "Received notification action broadcast with null issue action id");
return null;
}
try {
return SafetyCenterIds.issueActionIdFromString(issueActionIdString);
} catch (IllegalArgumentException e) {
- Log.w(TAG, "Could not decode the issue action ID", e);
+ Log.w(TAG, "Could not decode the issue action id", e);
return null;
}
}
@@ -162,22 +159,28 @@ public final class SafetyCenterNotificationReceiver extends BroadcastReceiver {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_NOTIFICATION_DISMISSED);
filter.addAction(ACTION_NOTIFICATION_ACTION_CLICKED);
- context.registerReceiver(this, filter, Context.RECEIVER_NOT_EXPORTED);
+ context.registerReceiver(/* receiver= */ this, filter, Context.RECEIVER_NOT_EXPORTED);
}
@Override
public void onReceive(Context context, Intent intent) {
- if (!SafetyCenterFlags.getSafetyCenterEnabled()
- || !SafetyCenterFlags.getNotificationsEnabled()) {
+ if (!SafetyCenterFlags.getSafetyCenterEnabled()) {
+ Log.i(TAG, "Received notification broadcast but Safety Center is disabled");
+ return;
+ }
+
+ if (!SafetyCenterFlags.getNotificationsEnabled()) {
+ // TODO(b/284271124): Decide what to do with existing notifications
+ Log.i(TAG, "Received notification broadcast but notifications are disabled");
return;
}
- Log.d(TAG, "Received broadcast with action " + intent.getAction());
String action = intent.getAction();
if (action == null) {
- Log.w(TAG, "Received broadcast with null action!");
+ Log.w(TAG, "Received broadcast with null action");
return;
}
+ Log.d(TAG, "Received broadcast with action: " + action);
switch (action) {
case ACTION_NOTIFICATION_DISMISSED:
@@ -240,16 +243,8 @@ public final class SafetyCenterNotificationReceiver extends BroadcastReceiver {
UserUtils.isManagedProfile(issueKey.getUserId(), context),
issue.getIssueTypeId(),
issue.getSeverityLevel(),
- isPrimaryAction(issue, issueActionId));
+ SafetySourceIssues.isPrimaryAction(
+ issue, issueActionId.getSafetySourceIssueActionId()));
}
}
-
- /** Returns {@code true} if {@code actionId} is the first action of {@code issue}. */
- private boolean isPrimaryAction(SafetySourceIssue issue, SafetyCenterIssueActionId actionId) {
- return !issue.getActions().isEmpty()
- && issue.getActions()
- .get(0)
- .getId()
- .equals(actionId.getSafetySourceIssueActionId());
- }
}
diff --git a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationSender.java b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationSender.java
index 72b1f0e95..d17090c34 100644
--- a/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationSender.java
+++ b/service/java/com/android/safetycenter/notifications/SafetyCenterNotificationSender.java
@@ -16,13 +16,11 @@
package com.android.safetycenter.notifications;
-import static android.os.Build.VERSION_CODES.TIRAMISU;
import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED;
import static com.android.safetycenter.internaldata.SafetyCenterIds.toUserFriendlyString;
import android.annotation.IntDef;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Notification;
import android.app.NotificationManager;
@@ -36,18 +34,19 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import androidx.annotation.RequiresApi;
+import androidx.annotation.Nullable;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.util.UserUtils;
import com.android.safetycenter.SafetyCenterFlags;
import com.android.safetycenter.SafetySourceIssueInfo;
+import com.android.safetycenter.SafetySourceIssues;
import com.android.safetycenter.UserProfileGroup;
import com.android.safetycenter.data.SafetyCenterDataManager;
import com.android.safetycenter.internaldata.SafetyCenterIds;
import com.android.safetycenter.internaldata.SafetyCenterIssueKey;
import com.android.safetycenter.logging.SafetyCenterStatsdLogger;
-import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import com.android.safetycenter.resources.SafetyCenterResourcesApk;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -66,7 +65,6 @@ import javax.annotation.concurrent.NotThreadSafe;
*
* @hide
*/
-@RequiresApi(TIRAMISU)
@NotThreadSafe
public final class SafetyCenterNotificationSender {
@@ -120,13 +118,13 @@ public final class SafetyCenterNotificationSender {
public static SafetyCenterNotificationSender newInstance(
Context context,
- SafetyCenterResourcesContext resourcesContext,
+ SafetyCenterResourcesApk safetyCenterResourcesApk,
SafetyCenterNotificationChannels notificationChannels,
SafetyCenterDataManager dataManager) {
return new SafetyCenterNotificationSender(
context,
new SafetyCenterNotificationFactory(
- context, notificationChannels, resourcesContext),
+ context, notificationChannels, safetyCenterResourcesApk),
dataManager);
}
@@ -137,7 +135,7 @@ public final class SafetyCenterNotificationSender {
* <p>The given {@link SafetyEvent} have type {@link
* SafetyEvent#SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED} and include issue and action IDs
* that correspond to a {@link SafetySourceIssue} for which a notification is currently
- * displayed. Otherwise this method has no effect.
+ * displayed. Otherwise, this method has no effect.
*
* @param sourceId of the source which reported the issue
* @param safetyEvent the source provided upon successful action resolution
@@ -145,6 +143,12 @@ public final class SafetyCenterNotificationSender {
*/
public void notifyActionSuccess(
String sourceId, SafetyEvent safetyEvent, @UserIdInt int userId) {
+ if (!SafetyCenterFlags.getNotificationsEnabled()) {
+ // TODO(b/284271124): Decide what to do with existing notifications if flag gets
+ // toggled.
+ return;
+ }
+
if (safetyEvent.getType() != SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED) {
Log.w(TAG, "Received safety event of wrong type");
return;
@@ -174,12 +178,8 @@ public final class SafetyCenterNotificationSender {
return;
}
- SafetySourceIssue.Action successfulAction = null;
- for (int i = 0; i < notifiedIssue.getActions().size(); i++) {
- if (notifiedIssue.getActions().get(i).getId().equals(sourceIssueActionId)) {
- successfulAction = notifiedIssue.getActions().get(i);
- }
- }
+ SafetySourceIssue.Action successfulAction =
+ SafetySourceIssues.findAction(notifiedIssue, sourceIssueActionId);
if (successfulAction == null) {
Log.w(TAG, "Successful action not found");
return;
@@ -224,6 +224,7 @@ public final class SafetyCenterNotificationSender {
*/
public void updateNotifications(@UserIdInt int userId) {
if (!SafetyCenterFlags.getNotificationsEnabled()) {
+ // TODO(b/284271124): Decide what to do with existing notifications
return;
}
@@ -286,7 +287,7 @@ public final class SafetyCenterNotificationSender {
fout.println();
}
- /** Get all of the key-issue pairs for which notifications should be posted or updated now. */
+ /** Gets all the key-issue pairs for which notifications should be posted or updated now. */
private ArrayMap<SafetyCenterIssueKey, SafetySourceIssue> getIssuesToNotify(
@UserIdInt int userId) {
ArrayMap<SafetyCenterIssueKey, SafetySourceIssue> result = new ArrayMap<>();
@@ -325,14 +326,20 @@ public final class SafetyCenterNotificationSender {
@NotificationBehaviorInternal
private int getBehavior(SafetySourceIssue issue, SafetyCenterIssueKey issueKey) {
if (SdkLevel.isAtLeastU()) {
- switch (issue.getNotificationBehavior()) {
+ int notificationBehavior = issue.getNotificationBehavior();
+ switch (notificationBehavior) {
case SafetySourceIssue.NOTIFICATION_BEHAVIOR_NEVER:
return NOTIFICATION_BEHAVIOR_INTERNAL_NEVER;
case SafetySourceIssue.NOTIFICATION_BEHAVIOR_DELAYED:
return NOTIFICATION_BEHAVIOR_INTERNAL_DELAYED;
case SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY:
return NOTIFICATION_BEHAVIOR_INTERNAL_IMMEDIATELY;
+ case SafetySourceIssue.NOTIFICATION_BEHAVIOR_UNSPECIFIED:
+ return getBehaviorForIssueWithUnspecifiedBehavior(issue, issueKey);
}
+ Log.w(
+ TAG,
+ "Unexpected SafetySourceIssue.NotificationBehavior: " + notificationBehavior);
}
// On Android T all issues are assumed to have "unspecified" behavior
return getBehaviorForIssueWithUnspecifiedBehavior(issue, issueKey);
diff --git a/service/java/com/android/safetycenter/notifications/package-info.java b/service/java/com/android/safetycenter/notifications/package-info.java
index 85b487b30..e16c06d58 100644
--- a/service/java/com/android/safetycenter/notifications/package-info.java
+++ b/service/java/com/android/safetycenter/notifications/package-info.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
@NonNullByDefault
+@RequiresTiramisuByDefault
package com.android.safetycenter.notifications;
import com.android.safetycenter.annotations.NonNullByDefault;
+import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/java/com/android/safetycenter/package-info.java b/service/java/com/android/safetycenter/package-info.java
index 0bccf89fa..72774d21e 100644
--- a/service/java/com/android/safetycenter/package-info.java
+++ b/service/java/com/android/safetycenter/package-info.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
@NonNullByDefault
+@RequiresTiramisuByDefault
package com.android.safetycenter;
import com.android.safetycenter.annotations.NonNullByDefault;
+import com.android.safetycenter.annotations.RequiresTiramisuByDefault;
diff --git a/service/lint-baseline.xml b/service/lint-baseline.xml
index 90ea8d411..dd7e79ef5 100644
--- a/service/lint-baseline.xml
+++ b/service/lint-baseline.xml
@@ -19,8 +19,24 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/modules/Permission/service/java/com/android/safetycenter/SafetyCenterService.java"
- line="660"
+ line="651"
column="40"/>
</issue>
+ <issue
+ id="NewApi"
+ message="Call requires API level 34 (current min is 33): `getDeduplicationGroup`">
+ <location
+ file="packages/modules/Permission/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java"
+ line="315"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 34 (current min is 33): `getDeduplicationId`">
+ <location
+ file="packages/modules/Permission/service/java/com/android/safetycenter/data/SafetyCenterIssueDeduplicator.java"
+ line="316"/>
+ </issue>
+
</issues> \ No newline at end of file
diff --git a/tests/cts/permission/Android.bp b/tests/cts/permission/Android.bp
new file mode 100644
index 000000000..4749124eb
--- /dev/null
+++ b/tests/cts/permission/Android.bp
@@ -0,0 +1,127 @@
+//
+// Copyright (C) 2008 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionTestCases",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+ static_libs: [
+ "ctstestrunner-axt",
+ "guava",
+ "android-ex-camera2",
+ "compatibility-device-util-axt",
+ "truth-prebuilt",
+ "androidx.annotation_annotation",
+ "platformprotosnano",
+ "permission-test-util-lib",
+ "nativetesthelper",
+ // TODO(b/175251166): remove once Android migrates to JUnit 4.12,
+ // which provides assertThrows
+ "testng",
+ "bluetooth-test-util-lib",
+ "CtsAccessibilityCommon",
+ "safety-center-internal-data",
+ "sts-device-util",
+ "platform-test-rules",
+ "CtsVirtualDeviceCommonLib",
+ ],
+ jni_libs: [
+ "libctspermission_jni",
+ "libpermissionmanager_native_test",
+ "libnativehelper_compat_libc++",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.aidl",
+ "src/**/*.kt",
+ ],
+ sdk_version: "test_current",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ data: [
+ ":AppThatDefinesUndefinedPermissionGroupElement",
+ ":AppThatDoesNotHaveBgLocationAccess",
+ ":CtsAdversarialPermissionDefinerApp",
+ ":CtsAdversarialPermissionUserApp",
+ ":CtsAppThatAccessesLocationOnCommand",
+ ":CtsAppThatAlsoDefinesPermissionA",
+ ":CtsAppThatAlsoDefinesPermissionADifferentCert",
+ ":CtsAppThatAlsoDefinesPermissionGroupADifferentCert",
+ ":CtsAppThatAlsoDefinesPermissionGroupADifferentCert30",
+ ":CtsAppThatDefinesPermissionA",
+ ":CtsAppThatDefinesPermissionInPlatformGroup",
+ ":CtsAppThatDefinesPermissionWithInvalidGroup",
+ ":CtsAppThatDefinesPermissionWithInvalidGroup30",
+ ":CtsAppThatHasNotificationListener",
+ ":CtsAppThatRequestsBluetoothPermission30",
+ ":CtsAppThatRequestsCalendarContactsBodySensorCustomPermission",
+ ":CtsAppThatRequestsBluetoothPermission31",
+ ":CtsAppThatRequestsBluetoothPermissionNeverForLocation31",
+ ":CtsAppThatRequestsContactsAndCallLogPermission16",
+ ":CtsAppThatRequestsContactsPermission15",
+ ":CtsAppThatRequestsContactsPermission16",
+ ":CtsAppThatRequestsLocationAndBackgroundPermission28",
+ ":CtsAppThatRequestsLocationAndBackgroundPermission29",
+ ":CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider",
+ ":CtsAppThatRequestsLocationPermission22",
+ ":CtsAppThatRequestsLocationPermission28",
+ ":CtsAppThatRequestsLocationPermission29",
+ ":CtsAppThatRequestsLocationPermission29v4",
+ ":CtsAppThatRequestsOneTimePermission",
+ ":CtsAppThatRequestsPermissionAandB",
+ ":CtsAppThatRequestsPermissionAandC",
+ ":CtsAppThatRequestsStoragePermission28",
+ ":CtsAppThatRequestsStoragePermission29",
+ ":CtsAppThatRunsRationaleTests",
+ ":CtsAppToTestRevokeSelfPermission",
+ ":CtsAppWithSharedUidThatRequestsLocationPermission28",
+ ":CtsAppWithSharedUidThatRequestsLocationPermission29",
+ ":CtsAppWithSharedUidThatRequestsNoPermissions",
+ ":CtsAppWithSharedUidThatRequestsPermissions",
+ ":CtsInstallPermissionDefinerApp",
+ ":CtsInstallPermissionEscalatorApp",
+ ":CtsInstallPermissionUserApp",
+ ":CtsRuntimePermissionDefinerApp",
+ ":CtsRuntimePermissionUserApp",
+ ":CtsStorageEscalationApp28",
+ ":CtsStorageEscalationApp29Full",
+ ":CtsStorageEscalationApp29Scoped",
+ ":CtsVictimPermissionDefinerApp",
+ ":CtsAppThatRequestsMultiplePermissionsWithMinMaxSdk",
+ ":CtsAppThatRequestsSystemAlertWindow22",
+ ":CtsAppThatRequestsSystemAlertWindow23",
+ ":CtsAppThatRequestCustomCameraPermission",
+ ":CtsAppThatRequestsDevicePermissions",
+ ],
+ per_testcase_directory: true,
+}
diff --git a/tests/cts/permission/AndroidManifest.xml b/tests/cts/permission/AndroidManifest.xml
new file mode 100644
index 000000000..43fd97bb2
--- /dev/null
+++ b/tests/cts/permission/AndroidManifest.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts"
+ android:targetSandboxVersion="2">
+
+ <!-- for android.permission.cts.PermissionGroupChange -->
+ <permission android:name="android.permission.cts.B"
+ android:protectionLevel="dangerous"
+ android:label="@string/perm_b"
+ android:permissionGroup="android.permission.cts.groupB"
+ android:description="@string/perm_b"/>
+
+ <!-- for android.permission.cts.PermissionGroupChange -->
+ <permission android:name="android.permission.cts.C"
+ android:protectionLevel="dangerous"
+ android:label="@string/perm_c"
+ android:permissionGroup="android.permission.cts.groupC"
+ android:description="@string/perm_c"/>
+
+ <!-- for android.permission.cts.LocationAccessCheckTest -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+
+ <!-- for android.permission.cts.NearbyDevicesRenouncePermissionTest -->
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
+
+ <!-- for android.permission.cts.PermissionGroupChange -->
+ <permission-group android:description="@string/perm_group_b"
+ android:label="@string/perm_group_b"
+ android:name="android.permission.cts.groupB"/>
+
+ <!-- for android.permission.cts.PermissionGroupChange -->
+ <permission-group android:description="@string/perm_group_c"
+ android:label="@string/perm_group_c"
+ android:name="android.permission.cts.groupC"/>
+
+ <uses-permission android:name="android.permission.INJECT_EVENTS"/>
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <activity android:name="android.permission.cts.PermissionStubActivity"
+ android:label="PermissionStubActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+
+ <service android:name="android.permission.cts.CtsNotificationListenerService"
+ android:exported="true"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService"/>
+ </intent-filter>
+ </service>
+ <service android:name=".AccessibilityTestService"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/test_accessibilityservice"/>
+ </service>
+ </application>
+
+ <!--
+ The CTS stubs package cannot be used as the target application here,
+ since that requires many permissions to be set. Instead, specify this
+ package itself as the target and include any stub activities needed.
+
+ This test package uses the default InstrumentationTestRunner, because
+ the InstrumentationCtsTestRunner is only available in the stubs
+ package. That runner cannot be added to this package either, since it
+ relies on hidden APIs.
+ -->
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permission.cts"
+ android:label="CTS tests of android.permission">
+ </instrumentation>
+
+</manifest>
diff --git a/tests/cts/permission/AndroidTest.xml b/tests/cts/permission/AndroidTest.xml
new file mode 100644
index 000000000..de9504dc7
--- /dev/null
+++ b/tests/cts/permission/AndroidTest.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<configuration description="Config for CTS Permission test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user"/>
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" />
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <!-- Keep screen on for Bluetooth scanning -->
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ <option name="screen-always-on" value="on" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <!-- Install main test suite apk -->
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionTestCases.apk" />
+ </target_preparer>
+
+ <!-- Create place to store apks -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts-permission" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts-permission"/>
+ </target_preparer>
+
+ <!-- Collect screen recordings -->
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/user/0/android.permission.cts/files" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <!-- Load additional APKs onto device -->
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="CtsAppThatRequestsPermissionAandB.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsPermissionAandB.apk" />
+ <option name="push" value="CtsAppThatRequestsPermissionAandC.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsPermissionAandC.apk" />
+ <option name="push" value="CtsAppThatRequestsBluetoothPermission30.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsBluetoothPermission30.apk" />
+ <option name="push" value="CtsAppThatRequestsBluetoothPermission31.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsBluetoothPermission31.apk" />
+ <option name="push" value="CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk" />
+ <option name="push" value="CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk" />
+ <option name="push" value="CtsAppThatRequestsContactsPermission16.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsContactsPermission16.apk" />
+ <option name="push" value="CtsAppThatRequestsContactsPermission15.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsContactsPermission15.apk" />
+ <option name="push" value="CtsAppThatRequestsContactsAndCallLogPermission16.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsContactsAndCallLogPermission16.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationPermission29.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationPermission29.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationPermission29v4.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationPermission29v4.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationPermission28.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationPermission28.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationPermission22.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationPermission22.apk" />
+ <option name="push" value="CtsAppThatRequestsStoragePermission29.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsStoragePermission29.apk" />
+ <option name="push" value="CtsAppThatRequestsStoragePermission28.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsStoragePermission28.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationAndBackgroundPermission28.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationAndBackgroundPermission28.apk" />
+ <option name="push" value="CtsAppThatRequestsLocationAndBackgroundPermission29.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsLocationAndBackgroundPermission29.apk" />
+ <option name="push" value="CtsAppThatAccessesLocationOnCommand.apk->/data/local/tmp/cts-permission/CtsAppThatAccessesLocationOnCommand.apk" />
+ <option name="push" value="AppThatDoesNotHaveBgLocationAccess.apk->/data/local/tmp/cts-permission/AppThatDoesNotHaveBgLocationAccess.apk" />
+ <option name="push" value="CtsAppWithSharedUidThatRequestsPermissions.apk->/data/local/tmp/cts-permission/CtsAppWithSharedUidThatRequestsPermissions.apk" />
+ <option name="push" value="CtsAppWithSharedUidThatRequestsNoPermissions.apk->/data/local/tmp/cts-permission/CtsAppWithSharedUidThatRequestsNoPermissions.apk" />
+ <option name="push" value="CtsAppWithSharedUidThatRequestsLocationPermission28.apk->/data/local/tmp/cts-permission/CtsAppWithSharedUidThatRequestsLocationPermission28.apk" />
+ <option name="push" value="CtsAppWithSharedUidThatRequestsLocationPermission29.apk->/data/local/tmp/cts-permission/CtsAppWithSharedUidThatRequestsLocationPermission29.apk" />
+ <option name="push" value="CtsAppThatRequestsCalendarContactsBodySensorCustomPermission.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsCalendarContactsBodySensorCustomPermission.apk" />
+ <option name="push" value="CtsAppThatRunsRationaleTests.apk->/data/local/tmp/cts-permission/CtsAppThatRunsRationaleTests.apk" />
+ <option name="push" value="CtsAdversarialPermissionUserApp.apk->/data/local/tmp/cts-permission/CtsAdversarialPermissionUserApp.apk" />
+ <option name="push" value="CtsAdversarialPermissionDefinerApp.apk->/data/local/tmp/cts-permission/CtsAdversarialPermissionDefinerApp.apk" />
+ <option name="push" value="CtsVictimPermissionDefinerApp.apk->/data/local/tmp/cts-permission/CtsVictimPermissionDefinerApp.apk" />
+ <option name="push" value="CtsRuntimePermissionDefinerApp.apk->/data/local/tmp/cts-permission/CtsRuntimePermissionDefinerApp.apk" />
+ <option name="push" value="CtsRuntimePermissionUserApp.apk->/data/local/tmp/cts-permission/CtsRuntimePermissionUserApp.apk" />
+ <option name="push" value="CtsInstallPermissionDefinerApp.apk->/data/local/tmp/cts-permission/CtsInstallPermissionDefinerApp.apk" />
+ <option name="push" value="CtsInstallPermissionUserApp.apk->/data/local/tmp/cts-permission/CtsInstallPermissionUserApp.apk" />
+ <option name="push" value="CtsInstallPermissionEscalatorApp.apk->/data/local/tmp/cts-permission/CtsInstallPermissionEscalatorApp.apk" />
+ <option name="push" value="CtsAppThatRequestsOneTimePermission.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsOneTimePermission.apk" />
+ <option name="push" value="CtsAppToTestRevokeSelfPermission.apk->/data/local/tmp/cts-permission/CtsAppToTestRevokeSelfPermission.apk" />
+ <option name="push" value="AppThatDefinesUndefinedPermissionGroupElement.apk->/data/local/tmp/cts-permission/AppThatDefinesUndefinedPermissionGroupElement.apk" />
+ <option name="push" value="CtsAppThatDefinesPermissionA.apk->/data/local/tmp/cts-permission/CtsAppThatDefinesPermissionA.apk" />
+ <option name="push" value="CtsAppThatAlsoDefinesPermissionA.apk->/data/local/tmp/cts-permission/CtsAppThatAlsoDefinesPermissionA.apk" />
+ <option name="push" value="CtsAppThatAlsoDefinesPermissionADifferentCert.apk->/data/local/tmp/cts-permission/CtsAppThatAlsoDefinesPermissionADifferentCert.apk" />
+ <option name="push" value="CtsAppThatAlsoDefinesPermissionGroupADifferentCert.apk->/data/local/tmp/cts-permission/CtsAppThatAlsoDefinesPermissionGroupADifferentCert.apk" />
+ <option name="push" value="CtsAppThatDefinesPermissionInPlatformGroup.apk->/data/local/tmp/cts-permission/CtsAppThatDefinesPermissionInPlatformGroup.apk" />
+ <option name="push" value="CtsAppThatAlsoDefinesPermissionGroupADifferentCert30.apk->/data/local/tmp/cts-permission/CtsAppThatAlsoDefinesPermissionGroupADifferentCert30.apk" />
+ <option name="push" value="CtsAppThatDefinesPermissionWithInvalidGroup.apk->/data/local/tmp/cts-permission/CtsAppThatDefinesPermissionWithInvalidGroup.apk" />
+ <option name="push" value="CtsAppThatDefinesPermissionWithInvalidGroup30.apk->/data/local/tmp/cts-permission/CtsAppThatDefinesPermissionWithInvalidGroup30.apk" />
+ <option name="push" value="CtsStorageEscalationApp28.apk->/data/local/tmp/cts-permission/CtsStorageEscalationApp28.apk" />
+ <option name="push" value="CtsStorageEscalationApp29Full.apk->/data/local/tmp/cts-permission/CtsStorageEscalationApp29Full.apk" />
+ <option name="push" value="CtsStorageEscalationApp29Scoped.apk->/data/local/tmp/cts-permission/CtsStorageEscalationApp29Scoped.apk" />
+ <option name="push" value="CtsAppThatHasNotificationListener.apk->/data/local/tmp/cts-permission/CtsAppThatHasNotificationListener.apk" />
+ <option name="push" value="CtsAppThatRequestsMultiplePermissionsWithMinMaxSdk.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsMultiplePermissionsWithMinMaxSdk.apk" />
+ <option name="push" value="CtsAppThatRequestsSystemAlertWindow22.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsSystemAlertWindow22.apk" />
+ <option name="push" value="CtsAppThatRequestsSystemAlertWindow23.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsSystemAlertWindow23.apk" />
+ <option name="push" value="CtsAppThatRequestCustomCameraPermission.apk->/data/local/tmp/cts-permission/CtsAppThatRequestCustomCameraPermission.apk" />
+ <option name="push" value="CtsAppThatRequestsDevicePermissions.apk->/data/local/tmp/cts-permission/CtsAppThatRequestsDevicePermissions.apk" />
+ </target_preparer>
+
+ <!-- Remove additional apps if installed -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- disable DeprecatedAbi warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.appthatrequestpermission" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.appthatrequestnopermission" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.AdversarialPermissionDefinerApp" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.VictimPermissionDefinerApp" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.userapp" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.runtimepermissiondefinerapp" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.revokepermissionwhenremoved.runtimepermissionuserapp" />
+ <option name="teardown-command" value="pm uninstall android.permission.cts.appthathasnotificationlistener" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permission.cts" />
+ <option name="runtime-hint" value="13m" />
+ </test>
+
+ <system_checker class="com.android.tradefed.suite.checker.UserChecker" >
+ <option name="user-cleanup" value="true" />
+ </system_checker>
+</configuration>
diff --git a/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/Android.bp b/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/Android.bp
new file mode 100644
index 000000000..fdb0be452
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsCalendarContactsBodySensorCustomPermission",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/AndroidManifest.xml b/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/AndroidManifest.xml
new file mode 100644
index 000000000..ef4d82dfc
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesCalendarContactsBodySensorCustomPermission/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestcustompermission"
+ android:versionCode="1">
+
+ <permission-group
+ android:name="android.permission.cts.appthatrequestcustompermission.TEST_GROUP"
+ android:label="test permission group"
+ android:protectionLevel="dangerous" />
+
+ <permission
+ android:name="android.permission.cts.appthatrequestcustompermission.TEST_PERMISSION"
+ android:label="test permission"
+ android:permissionGroup="android.permission.cts.appthatrequestcustompermission.TEST_GROUP"
+ android:protectionLevel="dangerous" />
+
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+ <uses-permission android:name="android.permission.cts.appthatrequestcustompermission.TEST_PERMISSION" />
+
+ <application />
+</manifest>
diff --git a/tests/cts/permission/AppThatAccessesLocationOnCommand/Android.bp b/tests/cts/permission/AppThatAccessesLocationOnCommand/Android.bp
new file mode 100644
index 000000000..2bb3dd3ab
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesLocationOnCommand/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAccessesLocationOnCommand",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.aidl"
+ ],
+}
diff --git a/tests/cts/permission/AppThatAccessesLocationOnCommand/AndroidManifest.xml b/tests/cts/permission/AppThatAccessesLocationOnCommand/AndroidManifest.xml
new file mode 100644
index 000000000..93836d389
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesLocationOnCommand/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthataccesseslocation">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+
+ <application android:label="CtsLocationAccess" android:debuggable="true">
+ <service android:name=".AccessLocationOnCommand"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/AccessLocationOnCommand.java b/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/AccessLocationOnCommand.java
new file mode 100644
index 000000000..75f4a0ce5
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/AccessLocationOnCommand.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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.permission.cts.appthataccesseslocation;
+
+import static android.location.Criteria.ACCURACY_FINE;
+
+import android.app.Service;
+import android.content.Intent;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+
+public class AccessLocationOnCommand extends Service {
+ private IAccessLocationOnCommand.Stub mBinder = new IAccessLocationOnCommand.Stub() {
+ public void accessLocation() {
+ Criteria crit = new Criteria();
+ crit.setAccuracy(ACCURACY_FINE);
+
+ AccessLocationOnCommand.this.getSystemService(LocationManager.class)
+ .requestSingleUpdate(crit, new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status,
+ Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+ }, Looper.getMainLooper());
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ return true;
+ }
+}
diff --git a/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl b/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl
new file mode 100644
index 000000000..be92ed160
--- /dev/null
+++ b/tests/cts/permission/AppThatAccessesLocationOnCommand/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 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.permission.cts.appthataccesseslocation;
+
+interface IAccessLocationOnCommand {
+ /** Access location on command */
+ void accessLocation();
+} \ No newline at end of file
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionA/Android.bp b/tests/cts/permission/AppThatAlsoDefinesPermissionA/Android.bp
new file mode 100644
index 000000000..46b7aecd3
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionA/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAlsoDefinesPermissionA",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ certificate: ":cts-testkey1",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionA/AndroidManifest.xml b/tests/cts/permission/AppThatAlsoDefinesPermissionA/AndroidManifest.xml
new file mode 100644
index 000000000..2a803017b
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionA/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatalsodefinespermissiona">
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"
+ android:permissionGroup="com.android.cts.duplicatepermission.groupA"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/Android.bp b/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/Android.bp
new file mode 100644
index 000000000..c88d0f7fe
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAlsoDefinesPermissionADifferentCert",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/AndroidManifest.xml b/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/AndroidManifest.xml
new file mode 100644
index 000000000..d333bf6df
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionADifferentCert/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissiona.differentcert">
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/Android.bp b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/Android.bp
new file mode 100644
index 000000000..b1ef695ac
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAlsoDefinesPermissionGroupADifferentCert",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/AndroidManifest.xml b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/AndroidManifest.xml
new file mode 100644
index 000000000..59cd518c1
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissiongroupa.differentcert">
+
+ <permission-group android:name="com.android.cts.duplicatepermission.groupA"
+ android:label="groupA"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/Android.bp b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/Android.bp
new file mode 100644
index 000000000..52900dfc3
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAlsoDefinesPermissionGroupADifferentCert30",
+ defaults: ["cts_defaults"],
+ sdk_version: "30",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/AndroidManifest.xml b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/AndroidManifest.xml
new file mode 100644
index 000000000..43ed9db58
--- /dev/null
+++ b/tests/cts/permission/AppThatAlsoDefinesPermissionGroupADifferentCert30/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissiongroupa.differentcert30">
+
+ <permission-group android:name="com.android.cts.duplicatepermission.groupA"
+ android:label="groupA"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesPermissionA/Android.bp b/tests/cts/permission/AppThatDefinesPermissionA/Android.bp
new file mode 100644
index 000000000..54a575b4f
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionA/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatDefinesPermissionA",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ certificate: ":cts-testkey1",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatDefinesPermissionA/AndroidManifest.xml b/tests/cts/permission/AppThatDefinesPermissionA/AndroidManifest.xml
new file mode 100644
index 000000000..527618c7d
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionA/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissiona">
+ <permission-group android:name="com.android.cts.duplicatepermission.groupA"
+ android:label="groupA"/>
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"
+ android:permissionGroup="com.android.cts.duplicatepermission.groupA"/>
+
+ <application/>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/Android.bp b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/Android.bp
new file mode 100644
index 000000000..9029b3a98
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatDefinesPermissionWithInvalidGroup",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/AndroidManifest.xml b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/AndroidManifest.xml
new file mode 100644
index 000000000..8abd4cc4a
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissionwithinvalidgroup">
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"
+ android:permissionGroup="com.android.cts.duplicatepermission.invalid"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/Android.bp b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/Android.bp
new file mode 100644
index 000000000..04961e265
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatDefinesPermissionWithInvalidGroup30",
+ defaults: ["cts_defaults"],
+ sdk_version: "30",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/AndroidManifest.xml b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/AndroidManifest.xml
new file mode 100644
index 000000000..2fc662c27
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithInvalidGroup30/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissionwithinvalidgroup30">
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"
+ android:permissionGroup="com.android.cts.duplicatepermission.invalid"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/Android.bp b/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/Android.bp
new file mode 100644
index 000000000..687ad7488
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatDefinesPermissionInPlatformGroup",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/AndroidManifest.xml b/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/AndroidManifest.xml
new file mode 100644
index 000000000..d4709eb9b
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesPermissionWithPlatformGroup/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatdefinespermissioninplatformgroup">
+
+ <permission android:name="com.android.cts.duplicatepermission.permA"
+ android:permissionGroup="android.permission-group.CAMERA"/>
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/Android.bp b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/Android.bp
new file mode 100644
index 000000000..c00d26d3a
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "AppThatDefinesUndefinedPermissionGroupElement",
+ defaults: ["cts_defaults"],
+ sdk_version: "test_current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+ srcs: ["src/**/*.kt"],
+}
diff --git a/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml
new file mode 100644
index 000000000..ab2ef79b2
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2">
+
+ <permission
+ android:name="android.permission.cts.appthatrequestpermission.TEST"
+ android:protectionLevel="dangerous"
+ android:permissionGroup="android.permission-group.UNDEFINED" />
+
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.TEST" />
+
+ <application android:label="CtsPermissionUnknownGroup">
+ <activity
+ android:name=".RequestPermissions"
+ android:exported="true"
+ android:visibleToInstantApps="true"/>
+ </application>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/src/android/permission/cts/appthatrequestpermission/RequestPermissions.kt b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/src/android/permission/cts/appthatrequestpermission/RequestPermissions.kt
new file mode 100644
index 000000000..8a2392921
--- /dev/null
+++ b/tests/cts/permission/AppThatDefinesUndefinedPermissionGroupElement/src/android/permission/cts/appthatrequestpermission/RequestPermissions.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 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.permission.cts.appthatrequestpermission
+
+import android.app.Activity
+import android.os.Bundle
+import android.util.Log
+
+class RequestPermissions : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)")
+ return
+ }
+
+ val permissions = intent.getStringArrayExtra(EXTRA_PERMISSIONS)!!
+ requestPermissions(permissions, 0)
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<String>,
+ grantResults: IntArray
+ ) {
+ finish()
+ }
+
+ companion object {
+ private const val EXTRA_PERMISSIONS =
+ "android.permission.cts.appthatrequestpermission.extra.PERMISSIONS"
+ private val TAG = RequestPermissions::class.simpleName
+ }
+} \ No newline at end of file
diff --git a/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/Android.bp b/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/Android.bp
new file mode 100644
index 000000000..f9ff21c6f
--- /dev/null
+++ b/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "AppThatDoesNotHaveBgLocationAccess",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/AndroidManifest.xml b/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/AndroidManifest.xml
new file mode 100644
index 000000000..8e883a4ad
--- /dev/null
+++ b/tests/cts/permission/AppThatDoesNotHaveBgLocationAccess/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthataccesseslocation">
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
+ <application android:label="CtsLocationAccess" android:debuggable="true"/>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatHasNotificationListener/Android.bp b/tests/cts/permission/AppThatHasNotificationListener/Android.bp
new file mode 100644
index 000000000..419ab5d66
--- /dev/null
+++ b/tests/cts/permission/AppThatHasNotificationListener/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatHasNotificationListener",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ sdk_version: "current",
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+}
diff --git a/tests/cts/permission/AppThatHasNotificationListener/AndroidManifest.xml b/tests/cts/permission/AppThatHasNotificationListener/AndroidManifest.xml
new file mode 100644
index 000000000..03d23dfb2
--- /dev/null
+++ b/tests/cts/permission/AppThatHasNotificationListener/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthathasnotificationlistener"
+ android:versionCode="1">
+
+ <application android:label="CtsNotificationListener">
+ <service
+ android:name=".CtsNotificationListenerService"
+ android:label="CtsNotificationListener"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService"/>
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java b/tests/cts/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java
new file mode 100644
index 000000000..2bd423e1b
--- /dev/null
+++ b/tests/cts/permission/AppThatHasNotificationListener/src/android/permission/cts/appthathasnotificationlistener/CtsNotificationListenerService.java
@@ -0,0 +1,21 @@
+/*
+ * 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.permission.cts.appthathasnotificationlistener;
+
+import android.service.notification.NotificationListenerService;
+
+public class CtsNotificationListenerService extends NotificationListenerService {}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermission30/Android.bp b/tests/cts/permission/AppThatRequestBluetoothPermission30/Android.bp
new file mode 100644
index 000000000..a3fe38109
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermission30/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "AppThatRequestBluetoothPermission",
+ srcs: [
+ "src/**/*.java",
+ ],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsBluetoothPermission30",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: [":AppThatRequestBluetoothPermission"],
+}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermission30/AndroidManifest.xml b/tests/cts/permission/AppThatRequestBluetoothPermission30/AndroidManifest.xml
new file mode 100644
index 000000000..d84e0d8f4
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermission30/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+
+ <application>
+ <provider
+ android:name=".AccessBluetoothOnCommand"
+ android:authorities="appthatrequestpermission"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java b/tests/cts/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java
new file mode 100644
index 000000000..a27da0bdc
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermission30/src/android/permission/cts/appthatrequestpermission/AccessBluetoothOnCommand.java
@@ -0,0 +1,161 @@
+/*
+ * 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.permission.cts.appthatrequestpermission;
+
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanResult;
+import android.content.AttributionSource;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.ContextParams;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Base64;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AccessBluetoothOnCommand extends ContentProvider {
+ private static final String TAG = "AccessBluetoothOnCommand";
+ private static final String DISAVOWAL_APP_PKG = "android.permission.cts.appneverforlocation";
+
+ private enum Result {
+ UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
+ }
+
+ @Override
+ public Bundle call(String authority, String method, String arg, Bundle extras) {
+ final Bundle res = new Bundle();
+
+ BluetoothLeScanner scanner = null;
+ ScanCallback scanCallback = null;
+
+ try {
+ Context context = ("PROXY".equals(arg)) ? createProxyingContext() : getContext();
+ scanner = context.getSystemService(BluetoothManager.class)
+ .getAdapter().getBluetoothLeScanner();
+
+ final Set<String> observedScans = ConcurrentHashMap.newKeySet();
+ final AtomicInteger observedErrorCode = new AtomicInteger(0);
+
+ scanCallback = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ Log.v(TAG, "onScanResult() - result = " + result);
+ observedScans.add(Base64.encodeToString(result.getScanRecord().getBytes(), 0));
+ }
+
+ @Override
+ public void onBatchScanResults(List<ScanResult> results) {
+ for (ScanResult result : results) {
+ onScanResult(0, result);
+ }
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ Log.v(TAG, "onScanFailed() - errorCode = " + errorCode);
+ observedErrorCode.set(errorCode);
+ }
+ };
+
+ scanner.startScan(scanCallback);
+
+ // Wait a few seconds to figure out what we actually observed
+ SystemClock.sleep(3000);
+
+ if (observedErrorCode.get() > 0) {
+ throw new RuntimeException("Scan returned error code: " + observedErrorCode.get());
+ }
+
+ switch (observedScans.size()) {
+ case 0:
+ res.putInt(Intent.EXTRA_INDEX, Result.EMPTY.ordinal());
+ break;
+ case 1:
+ res.putInt(Intent.EXTRA_INDEX, Result.FILTERED.ordinal());
+ break;
+ case 5:
+ res.putInt(Intent.EXTRA_INDEX, Result.FULL.ordinal());
+ break;
+ default:
+ res.putInt(Intent.EXTRA_INDEX, Result.UNKNOWN.ordinal());
+ break;
+ }
+ } catch (Throwable t) {
+ Log.v(TAG, "Failed to scan", t);
+ res.putInt(Intent.EXTRA_INDEX, Result.EXCEPTION.ordinal());
+ } finally {
+ try {
+ scanner.stopScan(scanCallback);
+ } catch (Exception e) {
+ }
+ }
+ return res;
+ }
+
+ private Context createProxyingContext() throws PackageManager.NameNotFoundException {
+ int disavowingAppUid =
+ getContext().getPackageManager().getPackageUid(DISAVOWAL_APP_PKG, 0);
+ AttributionSource attrib = new AttributionSource.Builder(disavowingAppUid)
+ .setPackageName(DISAVOWAL_APP_PKG)
+ .build();
+ return getContext().createContext(
+ new ContextParams.Builder().setNextAttributionSource(attrib).build());
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermission31/Android.bp b/tests/cts/permission/AppThatRequestBluetoothPermission31/Android.bp
new file mode 100644
index 000000000..7dc2e2445
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermission31/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsBluetoothPermission31",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: [":AppThatRequestBluetoothPermission"],
+}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermission31/AndroidManifest.xml b/tests/cts/permission/AppThatRequestBluetoothPermission31/AndroidManifest.xml
new file mode 100644
index 000000000..70b381170
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermission31/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
+
+ <application>
+ <provider
+ android:name=".AccessBluetoothOnCommand"
+ android:authorities="appthatrequestpermission"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/Android.bp b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/Android.bp
new file mode 100644
index 000000000..857f2e2f4
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsBluetoothPermissionNeverForLocation31",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: [":AppThatRequestBluetoothPermission"],
+}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/AndroidManifest.xml b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/AndroidManifest.xml
new file mode 100644
index 000000000..446933d21
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocation31/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_ADVERTISE"
+ android:usesPermissionFlags="neverForLocation" />
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_CONNECT"
+ android:usesPermissionFlags="neverForLocation" />
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_SCAN"
+ android:usesPermissionFlags="neverForLocation" />
+
+ <application>
+ <provider
+ android:name=".AccessBluetoothOnCommand"
+ android:authorities="appthatrequestpermission"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp
new file mode 100644
index 000000000..6f635c0cc
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/Android.bp
@@ -0,0 +1,32 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml
new file mode 100644
index 000000000..6b4a991be
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestBluetoothPermissionNeverForLocationNoProvider/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appneverforlocation">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_ADVERTISE"
+ android:usesPermissionFlags="neverForLocation" />
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_CONNECT"
+ android:usesPermissionFlags="neverForLocation" />
+ <uses-permission
+ android:name="android.permission.BLUETOOTH_SCAN"
+ android:usesPermissionFlags="neverForLocation" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/Android.bp b/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/Android.bp
new file mode 100644
index 000000000..1a057d010
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsContactsAndCallLogPermission16",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/AndroidManifest.xml b/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/AndroidManifest.xml
new file mode 100644
index 000000000..08f014508
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsAndCallLogPermission16/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="3">
+
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16" />
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestContactsPermission15/Android.bp b/tests/cts/permission/AppThatRequestContactsPermission15/Android.bp
new file mode 100644
index 000000000..54618447e
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsPermission15/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsContactsPermission15",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestContactsPermission15/AndroidManifest.xml b/tests/cts/permission/AppThatRequestContactsPermission15/AndroidManifest.xml
new file mode 100644
index 000000000..ab17c3668
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsPermission15/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2">
+
+ <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" />
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestContactsPermission16/Android.bp b/tests/cts/permission/AppThatRequestContactsPermission16/Android.bp
new file mode 100644
index 000000000..2dca5aa2c
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsPermission16/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsContactsPermission16",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestContactsPermission16/AndroidManifest.xml b/tests/cts/permission/AppThatRequestContactsPermission16/AndroidManifest.xml
new file mode 100644
index 000000000..703bb3a75
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestContactsPermission16/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="1">
+
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16" />
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestCustomCameraPermission/Android.bp b/tests/cts/permission/AppThatRequestCustomCameraPermission/Android.bp
new file mode 100644
index 000000000..873733d07
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestCustomCameraPermission/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestCustomCameraPermission",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "mts",
+ "sts",
+ "general-tests",
+ ],
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+}
diff --git a/tests/cts/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml b/tests/cts/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml
new file mode 100644
index 000000000..a8143a78e
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestCustomCameraPermission/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestcustomcamerapermission">
+
+ <permission android:name="appthatrequestcustomcamerapermission.CUSTOM"
+ android:permissionGroup="android.permission-group.CAMERA"
+ android:label="@string/permlab_custom"
+ android:description="@string/permdesc_custom"
+ android:protectionLevel="dangerous" />
+
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="appthatrequestcustomcamerapermission.CUSTOM" />
+
+ <application>
+ <activity android:name=".RequestCameraPermission" android:exported="true"
+ android:visibleToInstantApps="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml b/tests/cts/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml
new file mode 100644
index 000000000..8de46384b
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestCustomCameraPermission/res/values/strings.xml
@@ -0,0 +1,20 @@
+<!--
+ * 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.
+ -->
+
+<resources>
+ <string name="permlab_custom">Custom</string>
+ <string name="permdesc_custom">allows bypassing one-time permissions</string>
+</resources> \ No newline at end of file
diff --git a/tests/cts/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java b/tests/cts/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
new file mode 100644
index 000000000..288e7e1b3
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestCustomCameraPermission/src/android/permission/cts/appthatrequestcustomcamerapermission/RequestCameraPermission.java
@@ -0,0 +1,85 @@
+/*
+ * 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.permission.cts.appthatrequestcustomcamerapermission;
+
+import static android.Manifest.permission.CAMERA;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+
+public class RequestCameraPermission extends Activity {
+ private static final String LOG_TAG = RequestCameraPermission.class.getSimpleName();
+
+ public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+ private Handler mHandler;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ Log.w(LOG_TAG, "Activity was recreated. (Perhaps due to a configuration change?)");
+ return;
+ }
+
+ boolean cameraGranted =
+ checkSelfPermission(CAMERA) == PERMISSION_GRANTED;
+ boolean customGranted =
+ checkSelfPermission(CUSTOM_PERMISSION) == PERMISSION_GRANTED;
+
+ mHandler = new Handler(getMainLooper());
+
+ if (!cameraGranted && !customGranted) {
+ requestPermissions(new String[] {CAMERA}, 0);
+ } else {
+ Log.e(LOG_TAG, "Test app was opened with cameraGranted=" + cameraGranted
+ + " and customGranted=" + customGranted);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (requestCode == 0) {
+ if (grantResults[0] != PERMISSION_GRANTED) {
+ Log.e(LOG_TAG, "permission wasn't granted, this test should fail,"
+ + " leaving test app open.");
+ } else {
+ // Delayed request because the immediate request might show the dialog again
+ mHandler.postDelayed(() ->
+ requestPermissions(new String[] {CUSTOM_PERMISSION}, 1), 500);
+ }
+ } else if (requestCode == 1) {
+ if (grantResults[0] != PERMISSION_GRANTED) {
+ Log.e(LOG_TAG, "permission wasn't granted, this test should fail,"
+ + " leaving test app open.");
+ } else {
+ // Here camera was granted and custom was autogranted, exit process and let test
+ // verify both are revoked.
+
+ // Delayed exit because b/254675301
+ mHandler.postDelayed(() -> System.exit(0), 1000);
+ }
+ }
+
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestDevicePermissions/Android.bp b/tests/cts/permission/AppThatRequestDevicePermissions/Android.bp
new file mode 100644
index 000000000..c0a9f9914
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestDevicePermissions/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsDevicePermissions",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ srcs: ["src/**/*.kt"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestDevicePermissions/AndroidManifest.xml b/tests/cts/permission/AppThatRequestDevicePermissions/AndroidManifest.xml
new file mode 100644
index 000000000..a96342706
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestDevicePermissions/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2023 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <permission android:name="android.permission.cts.CUSTOM_SIGNATURE_PERMISSION"
+ android:protectionLevel="signature"/>
+ <uses-permission android:name="android.permission.cts.CUSTOM_SIGNATURE_PERMISSION" />
+
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <application>
+ <receiver
+ android:name="android.permission.cts.appthatrequestpermission.RevokeSelfPermissionReceiver"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.permission.cts.appthatrequestpermission.REVOKE_SELF_PERMISSION" />
+ </intent-filter>
+ </receiver>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestDevicePermissions/src/android/permission/cts/appthatrequestpermission/RevokeSelfPermissionReceiver.kt b/tests/cts/permission/AppThatRequestDevicePermissions/src/android/permission/cts/appthatrequestpermission/RevokeSelfPermissionReceiver.kt
new file mode 100644
index 000000000..e7b304e3f
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestDevicePermissions/src/android/permission/cts/appthatrequestpermission/RevokeSelfPermissionReceiver.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.permission.cts.appthatrequestpermission
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.os.Handler
+import android.os.Process
+
+/**
+ * Revokes permission for a device provided in the intent.
+ */
+class RevokeSelfPermissionReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val permissionName = intent.getStringExtra("permissionName")!!
+ val deviceId = intent.getIntExtra("deviceID", Context.DEVICE_ID_INVALID)
+ val deviceContext = context.createDeviceContext(deviceId)
+ deviceContext.revokeSelfPermissionOnKill(permissionName)
+
+ // revokeSelfPermissionOnKill is an async API, and the work is executed by main
+ // thread, so we add the kill to the queue to be executed after revoke call.
+ val handler = Handler.createAsync(context.mainLooper)
+ handler.postDelayed({
+ Process.killProcess(Process.myPid())
+ }, 1000)
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/Android.bp b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/Android.bp
new file mode 100644
index 000000000..5a60a3fbd
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationAndBackgroundPermission28",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts10",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/AndroidManifest.xml
new file mode 100644
index 000000000..626ee3d43
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission28/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="3">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <!-- The ACCESS_BACKGROUND_LOCATION was added for API 29. But apps targeting lower APK levels
+ can still request it to signal that they are aware of this new behavior -->
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/Android.bp b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/Android.bp
new file mode 100644
index 000000000..de6c3cbb2
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationAndBackgroundPermission29",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ min_sdk_version: "29",
+ target_sdk_version: "29",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/AndroidManifest.xml
new file mode 100644
index 000000000..285502cb2
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationAndBackgroundPermission29/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="3">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestLocationPermission22/Android.bp b/tests/cts/permission/AppThatRequestLocationPermission22/Android.bp
new file mode 100644
index 000000000..25d9893ec
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission22/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationPermission22",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationPermission22/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationPermission22/AndroidManifest.xml
new file mode 100644
index 000000000..78251baea
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission22/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="1">
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestLocationPermission28/Android.bp b/tests/cts/permission/AppThatRequestLocationPermission28/Android.bp
new file mode 100644
index 000000000..bfeadbd58
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission28/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationPermission28",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationPermission28/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationPermission28/AndroidManifest.xml
new file mode 100644
index 000000000..c8cf95761
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission28/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestLocationPermission29/Android.bp b/tests/cts/permission/AppThatRequestLocationPermission29/Android.bp
new file mode 100644
index 000000000..ee3982ea4
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission29/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationPermission29",
+ defaults: ["cts_defaults"],
+ min_sdk_version: "29",
+ target_sdk_version: "29",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationPermission29/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationPermission29/AndroidManifest.xml
new file mode 100644
index 000000000..17a0e0d35
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission29/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestLocationPermission29v4/Android.bp b/tests/cts/permission/AppThatRequestLocationPermission29v4/Android.bp
new file mode 100644
index 000000000..b56bb25eb
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission29v4/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsLocationPermission29v4",
+ defaults: ["cts_defaults"],
+ min_sdk_version: "29",
+ target_sdk_version: "29",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestLocationPermission29v4/AndroidManifest.xml b/tests/cts/permission/AppThatRequestLocationPermission29v4/AndroidManifest.xml
new file mode 100644
index 000000000..572222c49
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestLocationPermission29v4/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="4">
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/Android.bp b/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/Android.bp
new file mode 100644
index 000000000..5fcc6c8ba
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/Android.bp
@@ -0,0 +1,31 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsMultiplePermissionsWithMinMaxSdk",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/AndroidManifest.xml b/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/AndroidManifest.xml
new file mode 100644
index 000000000..e75a7f5c9
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestMultiplePermissionsWithMinMaxSdk/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2">
+
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.permissions.MINSDK_LT_DEVICESDK" android:minSdkVersion="32" />
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.permissions.MINSDK_GT_DEVICESDK" android:minSdkVersion="2147483647" />
+
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.permissions.MAXSDK_LT_DEVICESDK" android:maxSdkVersion="32" />
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.permissions.MAXSDK_GT_DEVICESDK" android:maxSdkVersion="2147483647" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestOneTimePermission/Android.bp b/tests/cts/permission/AppThatRequestOneTimePermission/Android.bp
new file mode 100644
index 000000000..c12a70871
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestOneTimePermission/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsOneTimePermission",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "mts-permission",
+ "general-tests",
+ ],
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/cts/permission/AppThatRequestOneTimePermission/AndroidManifest.xml b/tests/cts/permission/AppThatRequestOneTimePermission/AndroidManifest.xml
new file mode 100644
index 000000000..24fc537cf
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestOneTimePermission/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
+
+ <application>
+ <activity android:name=".RequestPermission" android:exported="true"
+ android:visibleToInstantApps="true" />
+ <service android:name=".KeepAliveForegroundService"
+ android:foregroundServiceType="specialUse"
+ android:exported="true"
+ android:visibleToInstantApps="true" >
+ <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="cts" />
+ </service>
+ </application>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/KeepAliveForegroundService.java b/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/KeepAliveForegroundService.java
new file mode 100644
index 000000000..e41a47321
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/KeepAliveForegroundService.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 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.permission.cts.appthatrequestpermission;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+
+public class KeepAliveForegroundService extends Service {
+
+ private static final String EXTRA_FOREGROUND_SERVICE_LIFESPAN =
+ "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_LIFESPAN";
+
+ private static final String EXTRA_FOREGROUND_SERVICE_STICKY =
+ "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_STICKY";
+
+ private static final String CHANNEL_ID = "channelId";
+ private static final String CHANNEL_NAME = "channelName";
+
+ private static final long DEFAULT_LIFESPAN = 5000;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ long lifespan;
+ boolean sticky;
+ if (intent == null) {
+ lifespan = DEFAULT_LIFESPAN;
+ sticky = false;
+ } else {
+ lifespan = intent.getLongExtra(EXTRA_FOREGROUND_SERVICE_LIFESPAN, DEFAULT_LIFESPAN);
+ sticky = intent.getBooleanExtra(EXTRA_FOREGROUND_SERVICE_STICKY, false);
+ }
+ NotificationManager notificationManager = getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(
+ new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
+ NotificationManager.IMPORTANCE_LOW));
+ Notification notification = new Notification.Builder(this, CHANNEL_ID)
+ .setSmallIcon(android.R.drawable.ic_lock_lock)
+ .build();
+ startForeground(1, notification);
+ new Handler(Looper.getMainLooper()).postDelayed(
+ () -> stopForeground(Service.STOP_FOREGROUND_REMOVE), lifespan);
+ if (sticky) {
+ return START_STICKY;
+ }
+ return super.onStartCommand(intent, flags, startId);
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/RequestPermission.java b/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
new file mode 100644
index 000000000..f2910c391
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestOneTimePermission/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2019 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.permission.cts.appthatrequestpermission;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class RequestPermission extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestPermissions(new String[] {"android.permission.ACCESS_FINE_LOCATION"}, 0);
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestPermissionAandB/Android.bp b/tests/cts/permission/AppThatRequestPermissionAandB/Android.bp
new file mode 100644
index 000000000..6c037b456
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandB/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsPermissionAandB",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/cts/permission/AppThatRequestPermissionAandB/AndroidManifest.xml b/tests/cts/permission/AppThatRequestPermissionAandB/AndroidManifest.xml
new file mode 100644
index 000000000..4c85a262b
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandB/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <permission android:name="android.permission.cts.appthatrequestpermission.A"
+ android:protectionLevel="dangerous"
+ android:label="@string/perm_a"
+ android:permissionGroup="android.permission.cts.groupB"
+ android:description="@string/perm_a" />
+
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.A" />
+ <uses-permission android:name="android.permission.cts.B" />
+
+ <application>
+ <activity android:name=".RequestPermission" android:exported="true"
+ android:visibleToInstantApps="true" />
+ </application>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestPermissionAandB/res/values/strings.xml b/tests/cts/permission/AppThatRequestPermissionAandB/res/values/strings.xml
new file mode 100644
index 000000000..563009789
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandB/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="perm_a">Permission A</string>
+</resources>
diff --git a/tests/cts/permission/AppThatRequestPermissionAandB/src/android/permission/cts/appthatrequestpermission/RequestPermission.java b/tests/cts/permission/AppThatRequestPermissionAandB/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
new file mode 100644
index 000000000..26671beb7
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandB/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.permission.cts.appthatrequestpermission;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class RequestPermission extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestPermissions(new String[] {"android.permission.cts.appthatrequestpermission.A",
+ "android.permission.cts.B"}, 0);
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestPermissionAandC/Android.bp b/tests/cts/permission/AppThatRequestPermissionAandC/Android.bp
new file mode 100644
index 000000000..b94965334
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandC/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsPermissionAandC",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/cts/permission/AppThatRequestPermissionAandC/AndroidManifest.xml b/tests/cts/permission/AppThatRequestPermissionAandC/AndroidManifest.xml
new file mode 100644
index 000000000..9b998311b
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandC/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission">
+
+ <permission android:name="android.permission.cts.appthatrequestpermission.A"
+ android:protectionLevel="dangerous"
+ android:label="@string/perm_a"
+ android:permissionGroup="android.permission.cts.groupC"
+ android:description="@string/perm_a" />
+
+ <uses-permission android:name="android.permission.cts.appthatrequestpermission.A" />
+ <uses-permission android:name="android.permission.cts.C" />
+
+ <application>
+ <activity android:name=".RequestPermission" android:exported="true"
+ android:visibleToInstantApps="true" />
+ </application>
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestPermissionAandC/res/values/strings.xml b/tests/cts/permission/AppThatRequestPermissionAandC/res/values/strings.xml
new file mode 100644
index 000000000..563009789
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandC/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="perm_a">Permission A</string>
+</resources>
diff --git a/tests/cts/permission/AppThatRequestPermissionAandC/src/android/permission/cts/appthatrequestpermission/RequestPermission.java b/tests/cts/permission/AppThatRequestPermissionAandC/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
new file mode 100644
index 000000000..ad72c4db2
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestPermissionAandC/src/android/permission/cts/appthatrequestpermission/RequestPermission.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.permission.cts.appthatrequestpermission;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class RequestPermission extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ requestPermissions(new String[] {"android.permission.cts.appthatrequestpermission.A",
+ "android.permission.cts.C"}, 0);
+ }
+}
diff --git a/tests/cts/permission/AppThatRequestStoragePermission28/Android.bp b/tests/cts/permission/AppThatRequestStoragePermission28/Android.bp
new file mode 100644
index 000000000..50ae9209b
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestStoragePermission28/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsStoragePermission28",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestStoragePermission28/AndroidManifest.xml b/tests/cts/permission/AppThatRequestStoragePermission28/AndroidManifest.xml
new file mode 100644
index 000000000..a847f39bd
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestStoragePermission28/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestStoragePermission29/Android.bp b/tests/cts/permission/AppThatRequestStoragePermission29/Android.bp
new file mode 100644
index 000000000..4663be9dc
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestStoragePermission29/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsStoragePermission29",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestStoragePermission29/AndroidManifest.xml b/tests/cts/permission/AppThatRequestStoragePermission29/AndroidManifest.xml
new file mode 100644
index 000000000..c783085a0
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestStoragePermission29/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="1">
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppThatRequestSystemAlertWindow22/Android.bp b/tests/cts/permission/AppThatRequestSystemAlertWindow22/Android.bp
new file mode 100644
index 000000000..43cc9de97
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestSystemAlertWindow22/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsSystemAlertWindow22",
+ target_sdk_version: "22",
+ certificate: ":cts-testkey2",
+ min_sdk_version: "22",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml b/tests/cts/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
new file mode 100644
index 000000000..bd13612d2
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestSystemAlertWindow22/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.usesystemalertwindowpermission">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/cts/permission/AppThatRequestSystemAlertWindow23/Android.bp b/tests/cts/permission/AppThatRequestSystemAlertWindow23/Android.bp
new file mode 100644
index 000000000..403257d45
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestSystemAlertWindow23/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRequestsSystemAlertWindow23",
+ target_sdk_version: "23",
+ certificate: ":cts-testkey2",
+ min_sdk_version: "23",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml b/tests/cts/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
new file mode 100644
index 000000000..bd13612d2
--- /dev/null
+++ b/tests/cts/permission/AppThatRequestSystemAlertWindow23/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.usesystemalertwindowpermission">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+</manifest>
diff --git a/tests/cts/permission/AppThatRunsRationaleTests/Android.bp b/tests/cts/permission/AppThatRunsRationaleTests/Android.bp
new file mode 100644
index 000000000..30019fba5
--- /dev/null
+++ b/tests/cts/permission/AppThatRunsRationaleTests/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatRunsRationaleTests",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "test_current",
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/cts/permission/AppThatRunsRationaleTests/AndroidManifest.xml b/tests/cts/permission/AppThatRunsRationaleTests/AndroidManifest.xml
new file mode 100644
index 000000000..4b7214fd6
--- /dev/null
+++ b/tests/cts/permission/AppThatRunsRationaleTests/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrunsrationaletests">
+
+ <uses-permission android:name="android.permission.READ_CONTACTS"/>
+
+ <application android:label="CtsRationaleTests">
+ <activity android:name=".TestActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppThatRunsRationaleTests/src/android/permission/cts/appthatrunsrationaletests/TestActivity.java b/tests/cts/permission/AppThatRunsRationaleTests/src/android/permission/cts/appthatrunsrationaletests/TestActivity.java
new file mode 100644
index 000000000..7544890ff
--- /dev/null
+++ b/tests/cts/permission/AppThatRunsRationaleTests/src/android/permission/cts/appthatrunsrationaletests/TestActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 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.permission.cts.appthatrunsrationaletests;
+
+import android.Manifest;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+public class TestActivity extends Activity {
+ private static final String CALLBACK_KEY = "testactivitycallback";
+ private static final String RESULT_KEY = "testactivityresult";
+ private static final String PERMISSION_NAME = Manifest.permission.READ_CONTACTS;
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+
+ RemoteCallback cb = (RemoteCallback) getIntent().getExtras().get(CALLBACK_KEY);
+
+ boolean result = shouldShowRequestPermissionRationale(PERMISSION_NAME);
+ Bundle res = new Bundle();
+ res.putBoolean(RESULT_KEY, result);
+
+ finish();
+ cb.sendResult(res);
+ }
+}
diff --git a/tests/cts/permission/AppToTestRevokeSelfPermission/Android.bp b/tests/cts/permission/AppToTestRevokeSelfPermission/Android.bp
new file mode 100644
index 000000000..6e200bf32
--- /dev/null
+++ b/tests/cts/permission/AppToTestRevokeSelfPermission/Android.bp
@@ -0,0 +1,35 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppToTestRevokeSelfPermission",
+ defaults: [
+ "cts_defaults",
+ "mts-target-sdk-version-current",
+ ],
+ min_sdk_version: "30",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "mts",
+ "general-tests",
+ ],
+ srcs: ["src/**/*.java"],
+}
diff --git a/tests/cts/permission/AppToTestRevokeSelfPermission/AndroidManifest.xml b/tests/cts/permission/AppToTestRevokeSelfPermission/AndroidManifest.xml
new file mode 100644
index 000000000..dbe58bfd5
--- /dev/null
+++ b/tests/cts/permission/AppToTestRevokeSelfPermission/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.apptotestrevokeselfpermission">
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
+
+ <application>
+ <activity android:name=".RevokePermission" android:exported="true"
+ android:visibleToInstantApps="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permission/AppToTestRevokeSelfPermission/src/android/permission/cts/apptotestselfrevokepermission/RevokePermission.java b/tests/cts/permission/AppToTestRevokeSelfPermission/src/android/permission/cts/apptotestselfrevokepermission/RevokePermission.java
new file mode 100644
index 000000000..b9a0ed7bb
--- /dev/null
+++ b/tests/cts/permission/AppToTestRevokeSelfPermission/src/android/permission/cts/apptotestselfrevokepermission/RevokePermission.java
@@ -0,0 +1,49 @@
+/*
+ * 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.permission.cts.apptotestrevokeselfpermission;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.Arrays;
+
+public class RevokePermission extends Activity {
+ private static final String TAG = "RevokePermission";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)");
+ return;
+ }
+
+ Intent intent = getIntent();
+ String[] permissions = intent.getStringArrayExtra("permissions");
+ if (permissions == null) {
+ return;
+ }
+ if (permissions.length == 1) {
+ getApplicationContext().revokeSelfPermissionOnKill(permissions[0]);
+ } else {
+ getApplicationContext().revokeSelfPermissionsOnKill(Arrays.asList(permissions));
+ }
+ }
+}
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/Android.bp b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/Android.bp
new file mode 100644
index 000000000..8214c425d
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppWithSharedUidThatRequestsLocationPermission28",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/AndroidManifest.xml b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/AndroidManifest.xml
new file mode 100644
index 000000000..ec69d1541
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission28/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="2"
+ android:sharedUserId="android.permission.cts.appthatrequestpermission">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/Android.bp b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/Android.bp
new file mode 100644
index 000000000..3df5c9a7d
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppWithSharedUidThatRequestsLocationPermission29",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/AndroidManifest.xml b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/AndroidManifest.xml
new file mode 100644
index 000000000..234192259
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestLocationPermission29/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:versionCode="1"
+ android:sharedUserId="android.permission.cts.appthatrequestpermission">
+
+ <!-- STOPSHIP: Set to apk level that shipped the location tristate -->
+ <!-- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" /> -->
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/Android.bp b/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/Android.bp
new file mode 100644
index 000000000..7dd3ef638
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppWithSharedUidThatRequestsNoPermissions",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/AndroidManifest.xml b/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/AndroidManifest.xml
new file mode 100644
index 000000000..0b34036ec
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestsNoPermissions/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestnopermission"
+ android:sharedUserId="cts.permissions">
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/Android.bp b/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/Android.bp
new file mode 100644
index 000000000..c58b3e81e
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppWithSharedUidThatRequestsPermissions",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/AndroidManifest.xml b/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/AndroidManifest.xml
new file mode 100644
index 000000000..ce02f17e1
--- /dev/null
+++ b/tests/cts/permission/AppWithSharedUidThatRequestsPermissions/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.appthatrequestpermission"
+ android:sharedUserId="cts.permissions">
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_CONTACTS" />
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+
+ <application />
+</manifest>
+
diff --git a/tests/cts/permission/OWNERS b/tests/cts/permission/OWNERS
new file mode 100644
index 000000000..6b284590c
--- /dev/null
+++ b/tests/cts/permission/OWNERS
@@ -0,0 +1,12 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
+
+per-file PowerManagerServicePermissionTest.java = file: platform/frameworks/base:/services/core/java/com/android/server/power/OWNERS
+per-file RequestLocation.java = tgunn@google.com
+
+per-file NoAudioPermissionTest.java = elaurent@google.com
+per-file MainlineNetworkStackPermissionTest.java = file: platform/frameworks/base:/services/net/OWNERS
+per-file Camera2PermissionTest.java = file: platform/frameworks/av:/camera/OWNERS
+per-file NoRollbackPermissionTest.java = mpgroover@google.com
+per-file EthernetManagerPermissionTest.java = file: platform/frameworks/base:/services/net/OWNERS \ No newline at end of file
diff --git a/tests/cts/permission/README b/tests/cts/permission/README
new file mode 100644
index 000000000..1ffc81f96
--- /dev/null
+++ b/tests/cts/permission/README
@@ -0,0 +1,16 @@
+Copyright (C) 2008 The Android Open Source Project
+
+Licensed under the Apache Licence, 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.
+
+In the permissions test cases, we just test the negative cases. These tests are to test the behavior of accessing the APIs without the required permission.
+
diff --git a/tests/cts/permission/StorageEscalationApp28/Android.bp b/tests/cts/permission/StorageEscalationApp28/Android.bp
new file mode 100644
index 000000000..9ea70f565
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp28/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2016 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStorageEscalationApp28",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/StorageEscalationApp28/AndroidManifest.xml b/tests/cts/permission/StorageEscalationApp28/AndroidManifest.xml
new file mode 100644
index 000000000..7b468bbf1
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp28/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2016 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.storageescalation">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+
+ <application android:hasCode="false" />
+</manifest>
diff --git a/tests/cts/permission/StorageEscalationApp29Full/Android.bp b/tests/cts/permission/StorageEscalationApp29Full/Android.bp
new file mode 100644
index 000000000..dcb64e68a
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp29Full/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2016 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStorageEscalationApp29Full",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/StorageEscalationApp29Full/AndroidManifest.xml b/tests/cts/permission/StorageEscalationApp29Full/AndroidManifest.xml
new file mode 100644
index 000000000..0ed8e0024
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp29Full/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2016 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.storageescalation">
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+
+ <application android:hasCode="false" android:requestLegacyExternalStorage="true"/>
+</manifest>
diff --git a/tests/cts/permission/StorageEscalationApp29Scoped/Android.bp b/tests/cts/permission/StorageEscalationApp29Scoped/Android.bp
new file mode 100644
index 000000000..8a780c07b
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp29Scoped/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2016 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStorageEscalationApp29Scoped",
+ certificate: ":cts-testkey2",
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+}
diff --git a/tests/cts/permission/StorageEscalationApp29Scoped/AndroidManifest.xml b/tests/cts/permission/StorageEscalationApp29Scoped/AndroidManifest.xml
new file mode 100644
index 000000000..0ce57c1b5
--- /dev/null
+++ b/tests/cts/permission/StorageEscalationApp29Scoped/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2016 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.storageescalation">
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+
+ <application android:hasCode="false" android:requestLegacyExternalStorage="false"/>
+</manifest>
diff --git a/tests/cts/permission/jni/Android.bp b/tests/cts/permission/jni/Android.bp
new file mode 100644
index 000000000..59f93a098
--- /dev/null
+++ b/tests/cts/permission/jni/Android.bp
@@ -0,0 +1,60 @@
+// Copyright (C) 2010 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test_library {
+ name: "libctspermission_jni",
+ sdk_version: "current",
+ srcs: [
+ "CtsPermissionsJniOnLoad.cpp",
+ "android_permission_cts_FileUtils.cpp",
+ ],
+ shared_libs: [
+ "libnativehelper_compat_libc++",
+ "liblog",
+ ],
+ stl: "c++_static",
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ gtest: false,
+}
+
+cc_test_library {
+ name: "libpermissionmanager_native_test",
+ sdk_version: "current",
+ compile_multilib: "both",
+ srcs: [
+ "PermissionManagerNativeJniTest.cpp"
+ ],
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ ],
+ static_libs: [
+ "libbase_ndk",
+ ],
+ whole_static_libs: [
+ "libnativetesthelper_jni"
+ ],
+ gtest: false,
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
diff --git a/tests/cts/permission/jni/CtsPermissionsJniOnLoad.cpp b/tests/cts/permission/jni/CtsPermissionsJniOnLoad.cpp
new file mode 100644
index 000000000..fab33bdc7
--- /dev/null
+++ b/tests/cts/permission/jni/CtsPermissionsJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+
+extern int register_android_permission_cts_FileUtils(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+ JNIEnv *env = NULL;
+
+ if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+ return JNI_ERR;
+ }
+
+ if (register_android_permission_cts_FileUtils(env)) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_4;
+}
diff --git a/tests/cts/permission/jni/PermissionManagerNativeJniTest.cpp b/tests/cts/permission/jni/PermissionManagerNativeJniTest.cpp
new file mode 100644
index 000000000..392007074
--- /dev/null
+++ b/tests/cts/permission/jni/PermissionManagerNativeJniTest.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "PermissionManagerNativeJniTest"
+
+#include <android/permission_manager.h>
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+class PermissionManagerNativeJniTest : public ::testing::Test {
+public:
+ void SetUp() override { }
+ void TearDown() override { }
+};
+
+//-------------------------------------------------------------------------------------------------
+TEST_F(PermissionManagerNativeJniTest, testCheckPermission) {
+ pid_t selfPid = ::getpid();
+ uid_t selfUid = ::getuid();
+
+ LOG(INFO) << "testCheckPermission: uid " << selfUid << ", pid" << selfPid;
+
+ int32_t result;
+ // Check some permission(s) we should have.
+ EXPECT_EQ(APermissionManager_checkPermission("android.permission.ACCESS_FINE_LOCATION",
+ selfPid, selfUid, &result),
+ PERMISSION_MANAGER_STATUS_OK);
+ EXPECT_EQ(result, PERMISSION_MANAGER_PERMISSION_GRANTED);
+
+ // Check some permission(s) we should not have.
+ EXPECT_EQ(APermissionManager_checkPermission("android.permission.MANAGE_USERS",
+ selfPid, selfUid, &result),
+ PERMISSION_MANAGER_STATUS_OK);
+ EXPECT_EQ(result, PERMISSION_MANAGER_PERMISSION_DENIED);
+}
+
diff --git a/tests/cts/permission/jni/android_permission_cts_FileUtils.cpp b/tests/cts/permission/jni/android_permission_cts_FileUtils.cpp
new file mode 100644
index 000000000..68c3c76d3
--- /dev/null
+++ b/tests/cts/permission/jni/android_permission_cts_FileUtils.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <android/log.h>
+#include <jni.h>
+#include <stdio.h>
+#include <linux/xattr.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
+#include <sys/capability.h>
+#include <grp.h>
+#include <pwd.h>
+#include <string.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+static jfieldID gFileStatusDevFieldID;
+static jfieldID gFileStatusInoFieldID;
+static jfieldID gFileStatusModeFieldID;
+static jfieldID gFileStatusNlinkFieldID;
+static jfieldID gFileStatusUidFieldID;
+static jfieldID gFileStatusGidFieldID;
+static jfieldID gFileStatusSizeFieldID;
+static jfieldID gFileStatusBlksizeFieldID;
+static jfieldID gFileStatusBlocksFieldID;
+static jfieldID gFileStatusAtimeFieldID;
+static jfieldID gFileStatusMtimeFieldID;
+static jfieldID gFileStatusCtimeFieldID;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/permission/src/android/permission/cts/FileUtils.java
+ *
+ * Copied from hidden API: frameworks/base/core/jni/android_os_FileUtils.cpp
+ */
+
+jboolean android_permission_cts_FileUtils_getFileStatus(JNIEnv* env,
+ jobject /* thiz */, jstring path, jobject fileStatus, jboolean statLinks)
+{
+ ScopedUtfChars cPath(env, path);
+ jboolean ret = false;
+ struct stat s;
+
+ int res = statLinks == true ? lstat(cPath.c_str(), &s)
+ : stat(cPath.c_str(), &s);
+
+ if (res == 0) {
+ ret = true;
+ if (fileStatus != NULL) {
+ env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
+ env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
+ env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
+ env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
+ env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
+ env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
+ env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
+ env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
+ env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
+ env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
+ env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
+ env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
+ }
+ }
+
+ return ret;
+}
+
+jstring android_permission_cts_FileUtils_getUserName(JNIEnv* env,
+ jobject /* thiz */, jint uid)
+{
+ struct passwd *pwd = getpwuid(uid);
+ return env->NewStringUTF(pwd->pw_name);
+}
+
+jstring android_permission_cts_FileUtils_getGroupName(JNIEnv* env,
+ jobject /* thiz */, jint gid)
+{
+ struct group *grp = getgrgid(gid);
+ return env->NewStringUTF(grp->gr_name);
+}
+
+static jboolean isPermittedCapBitSet(JNIEnv* env, jstring path, size_t capId)
+{
+ struct vfs_cap_data capData;
+ memset(&capData, 0, sizeof(capData));
+
+ ScopedUtfChars cPath(env, path);
+ ssize_t result = getxattr(cPath.c_str(), XATTR_NAME_CAPS, &capData,
+ sizeof(capData));
+ if (result <= 0)
+ {
+ __android_log_print(ANDROID_LOG_DEBUG, NULL,
+ "isPermittedCapBitSet(): getxattr(\"%s\") call failed: "
+ "return %zd (error: %s (%d))\n",
+ cPath.c_str(), result, strerror(errno), errno);
+ return false;
+ }
+
+ return (capData.data[CAP_TO_INDEX(capId)].permitted &
+ CAP_TO_MASK(capId)) != 0;
+}
+
+jboolean android_permission_cts_FileUtils_hasSetUidCapability(JNIEnv* env,
+ jobject /* clazz */, jstring path)
+{
+ return isPermittedCapBitSet(env, path, CAP_SETUID);
+}
+
+jboolean android_permission_cts_FileUtils_hasSetGidCapability(JNIEnv* env,
+ jobject /* clazz */, jstring path)
+{
+ return isPermittedCapBitSet(env, path, CAP_SETGID);
+}
+
+static bool throwNamedException(JNIEnv* env, const char* className,
+ const char* message)
+{
+ ScopedLocalRef<jclass> eClazz(env, env->FindClass(className));
+ if (eClazz.get() == NULL)
+ {
+ __android_log_print(ANDROID_LOG_ERROR, NULL,
+ "throwNamedException(): failed to find class %s, cannot throw",
+ className);
+ return false;
+ }
+
+ env->ThrowNew(eClazz.get(), message);
+ return true;
+}
+
+// fill vfs_cap_data's permitted caps given a Java int[] of cap ids
+static bool fillPermittedCaps(vfs_cap_data* capData, JNIEnv* env, jintArray capIds)
+{
+ ScopedIntArrayRO cCapIds(env, capIds);
+ const size_t capCount = cCapIds.size();
+
+ for (size_t i = 0; i < capCount; ++i)
+ {
+ const jint capId = cCapIds[i];
+ if (!cap_valid(capId))
+ {
+ char message[64];
+ snprintf(message, sizeof(message),
+ "capability id %d out of valid range", capId);
+ throwNamedException(env, "java/lang/IllegalArgumentException",
+ message);
+
+ return false;
+ }
+ capData->data[CAP_TO_INDEX(capId)].permitted |= CAP_TO_MASK(capId);
+ }
+ return true;
+}
+
+jboolean android_permission_cts_FileUtils_CapabilitySet_fileHasOnly(JNIEnv* env,
+ jobject /* clazz */, jstring path, jintArray capIds)
+{
+ struct vfs_cap_data expectedCapData;
+ memset(&expectedCapData, 0, sizeof(expectedCapData));
+
+ expectedCapData.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE;
+ if (!fillPermittedCaps(&expectedCapData, env, capIds))
+ {
+ // exception thrown
+ return false;
+ }
+
+ struct vfs_cap_data actualCapData;
+ memset(&actualCapData, 0, sizeof(actualCapData));
+
+ ScopedUtfChars cPath(env, path);
+ ssize_t result = getxattr(cPath.c_str(), XATTR_NAME_CAPS, &actualCapData,
+ sizeof(actualCapData));
+ if (result <= 0)
+ {
+ __android_log_print(ANDROID_LOG_DEBUG, NULL,
+ "fileHasOnly(): getxattr(\"%s\") call failed: "
+ "return %zd (error: %s (%d))\n",
+ cPath.c_str(), result, strerror(errno), errno);
+ return false;
+ }
+
+ return (memcmp(&expectedCapData, &actualCapData,
+ sizeof(struct vfs_cap_data)) == 0);
+}
+
+static JNINativeMethod gMethods[] = {
+ { "getFileStatus", "(Ljava/lang/String;Landroid/permission/cts/FileUtils$FileStatus;Z)Z",
+ (void *) android_permission_cts_FileUtils_getFileStatus },
+ { "getUserName", "(I)Ljava/lang/String;",
+ (void *) android_permission_cts_FileUtils_getUserName },
+ { "getGroupName", "(I)Ljava/lang/String;",
+ (void *) android_permission_cts_FileUtils_getGroupName },
+ { "hasSetUidCapability", "(Ljava/lang/String;)Z",
+ (void *) android_permission_cts_FileUtils_hasSetUidCapability },
+ { "hasSetGidCapability", "(Ljava/lang/String;)Z",
+ (void *) android_permission_cts_FileUtils_hasSetGidCapability },
+};
+
+static JNINativeMethod gCapabilitySetMethods[] = {
+ { "fileHasOnly", "(Ljava/lang/String;[I)Z",
+ (void *) android_permission_cts_FileUtils_CapabilitySet_fileHasOnly },
+};
+
+int register_android_permission_cts_FileUtils(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/permission/cts/FileUtils");
+
+ jclass fileStatusClass = env->FindClass("android/permission/cts/FileUtils$FileStatus");
+ gFileStatusDevFieldID = env->GetFieldID(fileStatusClass, "dev", "I");
+ gFileStatusInoFieldID = env->GetFieldID(fileStatusClass, "ino", "I");
+ gFileStatusModeFieldID = env->GetFieldID(fileStatusClass, "mode", "I");
+ gFileStatusNlinkFieldID = env->GetFieldID(fileStatusClass, "nlink", "I");
+ gFileStatusUidFieldID = env->GetFieldID(fileStatusClass, "uid", "I");
+ gFileStatusGidFieldID = env->GetFieldID(fileStatusClass, "gid", "I");
+ gFileStatusSizeFieldID = env->GetFieldID(fileStatusClass, "size", "J");
+ gFileStatusBlksizeFieldID = env->GetFieldID(fileStatusClass, "blksize", "I");
+ gFileStatusBlocksFieldID = env->GetFieldID(fileStatusClass, "blocks", "J");
+ gFileStatusAtimeFieldID = env->GetFieldID(fileStatusClass, "atime", "J");
+ gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
+ gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");
+
+ jint result = env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(JNINativeMethod));
+ if (result)
+ {
+ return result;
+ }
+
+ // register FileUtils.CapabilitySet native methods
+ jclass capClazz = env->FindClass("android/permission/cts/FileUtils$CapabilitySet");
+
+ return env->RegisterNatives(capClazz, gCapabilitySetMethods,
+ sizeof(gCapabilitySetMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/cts/permission/nativeTests/Android.bp b/tests/cts/permission/nativeTests/Android.bp
new file mode 100644
index 000000000..40f8b6e0d
--- /dev/null
+++ b/tests/cts/permission/nativeTests/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CtsPermissionManagerNativeTestCases",
+
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
+
+ srcs: ["src/PermissionManagerNativeTest.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libandroid",
+ ],
+
+ static_libs: [
+ "libgtest_ndk_c++",
+ "libbase_ndk",
+ ],
+ stl: "libc++_static",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permission/nativeTests/AndroidTest.xml b/tests/cts/permission/nativeTests/AndroidTest.xml
new file mode 100644
index 000000000..f477231ef
--- /dev/null
+++ b/tests/cts/permission/nativeTests/AndroidTest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Config for CTS PermissionManager native test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ <option name="force-root" value="false" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsPermissionManagerNativeTestCases->/data/local/tmp/CtsPermissionManagerNativeTestCases" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="CtsPermissionManagerNativeTestCases" />
+ <option name="runtime-hint" value="15s" />
+ </test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
+</configuration>
diff --git a/tests/cts/permission/nativeTests/src/PermissionManagerNativeTest.cpp b/tests/cts/permission/nativeTests/src/PermissionManagerNativeTest.cpp
new file mode 100644
index 000000000..1b0dc06ea
--- /dev/null
+++ b/tests/cts/permission/nativeTests/src/PermissionManagerNativeTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "PermissionManagerNativeTest"
+
+#include <android/permission_manager.h>
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+//-----------------------------------------------------------------
+class PermissionManagerNativeTest : public ::testing::Test {
+
+protected:
+ PermissionManagerNativeTest() { }
+
+ virtual ~PermissionManagerNativeTest() { }
+
+ /* Test setup*/
+ virtual void SetUp() { }
+
+ /* Test tear down */
+ virtual void TearDown() { }
+};
+
+//-------------------------------------------------------------------------------------------------
+TEST_F(PermissionManagerNativeTest, testCheckPermission) {
+ pid_t selfPid = ::getpid();
+ uid_t selfUid = ::getuid();
+
+ LOG(INFO) << "testCheckPermission: uid " << selfUid << ", pid" << selfPid;
+
+ // Test is set up to force unroot by RootTargetPreparer, so we should be running as SHELL.
+ // Check some permissions SHELL should definitely have or not have.
+ int32_t result;
+ EXPECT_EQ(APermissionManager_checkPermission("android.permission.DUMP",
+ selfPid, selfUid, &result),
+ PERMISSION_MANAGER_STATUS_OK);
+ EXPECT_EQ(result, PERMISSION_MANAGER_PERMISSION_GRANTED);
+
+ EXPECT_EQ(APermissionManager_checkPermission("android.permission.MANAGE_USERS",
+ selfPid, selfUid, &result),
+ PERMISSION_MANAGER_STATUS_OK);
+ EXPECT_EQ(result, PERMISSION_MANAGER_PERMISSION_DENIED);
+
+ EXPECT_EQ(APermissionManager_checkPermission("android.permission.NETWORK_STACK",
+ selfPid, selfUid, &result),
+ PERMISSION_MANAGER_STATUS_OK);
+ EXPECT_EQ(result, PERMISSION_MANAGER_PERMISSION_DENIED);
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/Android.bp b/tests/cts/permission/permissionTestUtilLib/Android.bp
new file mode 100644
index 000000000..2f7004d5f
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/Android.bp
@@ -0,0 +1,37 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+ name: "permission-test-util-lib",
+
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ visibility: [
+ "//packages/modules/Permission:__subpackages__",
+ "//cts:__subpackages__",
+ ],
+ static_libs: [
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "androidx.test.ext.junit-nodeps",
+ ],
+
+ sdk_version: "test_current",
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerHelperRule.kt b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerHelperRule.kt
new file mode 100644
index 000000000..d992accb1
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerHelperRule.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 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.permission.cts
+
+import android.content.ComponentName
+import android.content.Context
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * Rule that enables and disables the CTS NotificationListenerService
+ */
+class CtsNotificationListenerHelperRule(context: Context) : TestRule {
+
+ private val notificationListenerComponentName = ComponentName(
+ context,
+ CtsNotificationListenerService::class.java
+ )
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ try {
+ // Allow NLS used to verify notifications sent
+ SystemUtil.runShellCommand(ALLOW_NLS_COMMAND +
+ notificationListenerComponentName.flattenToString())
+
+ base.evaluate()
+ } finally {
+ // Disallow NLS used to verify notifications sent
+ SystemUtil.runShellCommand(DISALLOW_NLS_COMMAND +
+ notificationListenerComponentName.flattenToString())
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val ALLOW_NLS_COMMAND = "cmd notification allow_listener "
+ private const val DISALLOW_NLS_COMMAND = "cmd notification disallow_listener "
+ }
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerService.java b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerService.java
new file mode 100644
index 000000000..6ffdd6fcf
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerService.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.permission.cts;
+
+import android.service.notification.NotificationListenerService;
+import android.util.Log;
+
+/**
+ * Implementation of {@link NotificationListenerService} for CTS tests.
+ *
+ * <p>In order to use this service in a test suite, ensure this service is declared in the test
+ * suite's AndroidManifest.xml as follows:
+ *
+ * <pre>{@code
+ * <service android:name="android.permission.cts.CtsNotificationListenerService"
+ * android:exported="true"
+ * android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.notification.NotificationListenerService"/>
+ * </intent-filter>
+ * </service>
+ * }</pre>
+ */
+public class CtsNotificationListenerService extends NotificationListenerService {
+ private static final String LOG_TAG = CtsNotificationListenerService.class.getSimpleName();
+
+ private static final Object sLock = new Object();
+
+ private static CtsNotificationListenerService sService;
+
+ @Override
+ public void onListenerConnected() {
+ Log.i(LOG_TAG, "connected");
+ synchronized (sLock) {
+ sService = this;
+ sLock.notifyAll();
+ }
+ }
+
+ public static NotificationListenerService getInstance() throws Exception {
+ synchronized (sLock) {
+ if (sService == null) {
+ sLock.wait(5000);
+ }
+
+ return sService;
+ }
+ }
+
+ @Override
+ public void onListenerDisconnected() {
+ Log.i(LOG_TAG, "disconnected");
+
+ synchronized (sLock) {
+ sService = null;
+ }
+ }
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerServiceUtils.kt b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerServiceUtils.kt
new file mode 100644
index 000000000..bf2a32e9a
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/CtsNotificationListenerServiceUtils.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 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.permission.cts
+
+import android.permission.cts.TestUtils.ensure
+import android.permission.cts.TestUtils.eventually
+import android.service.notification.StatusBarNotification
+import org.junit.Assert
+
+object CtsNotificationListenerServiceUtils {
+
+ private const val NOTIFICATION_CANCELLATION_TIMEOUT_MILLIS = 5000L
+ private const val NOTIFICATION_WAIT_MILLIS = 2000L
+
+ @JvmStatic
+ fun assertEmptyNotification(packageName: String, notificationId: Int) {
+ ensure({
+ Assert.assertNull(
+ "Expected no notification",
+ getNotification(packageName, notificationId))
+ }, NOTIFICATION_WAIT_MILLIS)
+ }
+
+ @JvmStatic
+ fun assertNotificationExist(packageName: String, notificationId: Int) {
+ eventually({
+ Assert.assertNotNull(
+ "Expected notification, none found",
+ getNotification(packageName, notificationId))
+ }, NOTIFICATION_WAIT_MILLIS)
+ }
+
+ @JvmStatic
+ fun cancelNotification(packageName: String, notificationId: Int) {
+ val notificationService = CtsNotificationListenerService.getInstance()
+ val notification = getNotification(packageName, notificationId)
+ if (notification != null) {
+ notificationService.cancelNotification(notification.key)
+ eventually({
+ Assert.assertTrue(getNotification(packageName, notificationId) == null)
+ }, NOTIFICATION_CANCELLATION_TIMEOUT_MILLIS)
+ }
+ }
+
+ @JvmStatic
+ fun cancelNotifications(packageName: String) {
+ val notificationService = CtsNotificationListenerService.getInstance()
+ val notifications = getNotifications(packageName)
+ if (notifications.isNotEmpty()) {
+ notifications.forEach { notification ->
+ notificationService.cancelNotification(notification.key)
+ }
+ eventually({
+ Assert.assertTrue(getNotifications(packageName).isEmpty())
+ }, NOTIFICATION_CANCELLATION_TIMEOUT_MILLIS)
+ }
+ }
+
+ @JvmStatic
+ fun getNotification(packageName: String, notificationId: Int): StatusBarNotification? {
+ return getNotifications(packageName).firstOrNull {
+ it.id == notificationId
+ }
+ }
+
+ @JvmStatic
+ fun getNotifications(packageName: String): List<StatusBarNotification> {
+ val notifications: MutableList<StatusBarNotification> = ArrayList()
+ val notificationService = CtsNotificationListenerService.getInstance()
+ for (notification in notificationService.activeNotifications) {
+ if (notification.packageName == packageName) {
+ notifications.add(notification)
+ }
+ }
+ return notifications
+ }
+
+ /**
+ * Get a notification listener notification that is currently visible.
+ *
+ * @param cancelNotification if `true` the notification is canceled inside this method
+ * @return The notification or `null` if there is none
+ */
+ @JvmStatic
+ @Throws(Throwable::class)
+ fun getNotificationForPackageAndId(
+ pkg: String,
+ id: Int,
+ cancelNotification: Boolean
+ ): StatusBarNotification? {
+ val notifications: List<StatusBarNotification> = getNotifications(pkg)
+ if (notifications.isEmpty()) {
+ return null
+ }
+ for (notification in notifications) {
+ if (notification.id == id) {
+ if (cancelNotification) {
+ cancelNotification(pkg, id)
+ }
+ return notification
+ }
+ }
+ return null
+ }
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/MtsIgnore.java b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/MtsIgnore.java
new file mode 100644
index 000000000..54c0c9a9c
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/MtsIgnore.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 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.permission.cts;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface MtsIgnore {
+ /**
+ * An optional bug number associated with the test. -1 Means that no bug number is associated.
+ *
+ * @return int
+ */
+ int bugId() default -1;
+
+ /**
+ * Details, such as the reason of why we're ignoring the test.
+ *
+ * @return String
+ */
+ String detail() default "";
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/PermissionUtils.java b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/PermissionUtils.java
new file mode 100644
index 000000000..6bbf8b52e
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/PermissionUtils.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
+import static android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS;
+import static android.Manifest.permission.MANAGE_APP_OPS_MODES;
+import static android.Manifest.permission.PACKAGE_USAGE_STATS;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OPSTR_GET_USAGE_STATS;
+import static android.app.AppOpsManager.permissionToOp;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+import static android.permission.cts.TestUtils.awaitJobUntilRequestedState;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.waitForBroadcastDispatch;
+
+import android.app.AppOpsManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.modules.utils.build.SdkLevel;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Common utils for permission tests
+ */
+public class PermissionUtils {
+ private static final int TESTED_FLAGS = FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED
+ | FLAG_PERMISSION_REVOKE_ON_UPGRADE | FLAG_PERMISSION_REVIEW_REQUIRED
+ | FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+
+ private static final String LOG_TAG = PermissionUtils.class.getSimpleName();
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private static final UiAutomation sUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ private PermissionUtils() {
+ // this class should never be instantiated
+ }
+
+ /**
+ * Get the state of an app-op.
+ *
+ * @param packageName The package the app-op belongs to
+ * @param permission The permission the app-op belongs to
+ *
+ * @return The mode the op is on
+ */
+ public static int getAppOp(@NonNull String packageName, @NonNull String permission)
+ throws Exception {
+ return sContext.getSystemService(AppOpsManager.class).unsafeCheckOpRaw(
+ permissionToOp(permission),
+ sContext.getPackageManager().getPackageUid(packageName, 0), packageName);
+ }
+
+ /**
+ * Install an APK.
+ *
+ * @param apkFile The apk to install
+ */
+ public static void install(@NonNull String apkFile) {
+ final int sdkVersion = Build.VERSION.SDK_INT
+ + (Build.VERSION.RELEASE_OR_CODENAME.equals("REL") ? 0 : 1);
+ boolean forceQueryable = sdkVersion > Build.VERSION_CODES.Q;
+ runShellCommandOrThrow("pm install -r --force-sdk "
+ + (SdkLevel.isAtLeastU() ? "--bypass-low-target-sdk-block " : "")
+ + (forceQueryable ? "--force-queryable " : "")
+ + apkFile);
+ }
+
+ /**
+ * Uninstall a package.
+ *
+ * @param packageName Name of package to be uninstalled
+ */
+ public static void uninstallApp(@NonNull String packageName) {
+ runShellCommand("pm uninstall " + packageName);
+ }
+
+ /**
+ * Set a new state for an app-op (using the permission-name)
+ *
+ * @param packageName The package the app-op belongs to
+ * @param permission The permission the app-op belongs to
+ * @param mode The new mode
+ */
+ public static void setAppOp(@NonNull String packageName, @NonNull String permission, int mode) {
+ setAppOpByName(packageName, permissionToOp(permission), mode);
+ }
+
+ /**
+ * Set a new state for an app-op (using the app-op-name)
+ *
+ * @param packageName The package the app-op belongs to
+ * @param op The name of the op
+ * @param mode The new mode
+ */
+ public static void setAppOpByName(@NonNull String packageName, @NonNull String op, int mode) {
+ runWithShellPermissionIdentity(
+ () -> sContext.getSystemService(AppOpsManager.class).setUidMode(op,
+ sContext.getPackageManager().getPackageUid(packageName, 0), mode),
+ MANAGE_APP_OPS_MODES);
+ }
+
+ /**
+ * Checks a permission. Does <u>not</u> check the appOp.
+ *
+ * <p>Users should use {@link #isGranted} instead.
+ *
+ * @param packageName The package that might have the permission granted
+ * @param permission The permission that might be granted
+ *
+ * @return {@code true} iff the permission is granted
+ */
+ public static boolean isPermissionGranted(@NonNull String packageName,
+ @NonNull String permission) throws Exception {
+ return sContext.checkPermission(permission, Process.myPid(),
+ sContext.getPackageManager().getPackageUid(packageName, 0))
+ == PERMISSION_GRANTED;
+ }
+
+ /**
+ * Checks if a permission is granted for a package.
+ *
+ * <p>This correctly handles pre-M apps by checking the app-ops instead.
+ * <p>This also correctly handles the location background permission, but does not handle any
+ * other background permission
+ *
+ * @param packageName The package that might have the permission granted
+ * @param permission The permission that might be granted
+ *
+ * @return {@code true} iff the permission is granted
+ */
+ public static boolean isGranted(@NonNull String packageName, @NonNull String permission)
+ throws Exception {
+ if (!isPermissionGranted(packageName, permission)) {
+ return false;
+ }
+
+ if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
+ // The app-op for background location is encoded into the mode of the foreground
+ // location
+ return getAppOp(packageName, ACCESS_COARSE_LOCATION) == MODE_ALLOWED;
+ } else {
+ int mode = getAppOp(packageName, permission);
+ return mode == MODE_ALLOWED || mode == MODE_FOREGROUND;
+ }
+ }
+
+ /**
+ * Grant a permission to an app.
+ *
+ * <p>This correctly handles pre-M apps by setting the app-ops.
+ * <p>This also correctly handles the location background permission, but does not handle any
+ * other background permission
+ *
+ * @param packageName The app that should have the permission granted
+ * @param permission The permission to grant
+ */
+ public static void grantPermission(@NonNull String packageName, @NonNull String permission)
+ throws Exception {
+ sUiAutomation.grantRuntimePermission(packageName, permission);
+
+ if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
+ // The app-op for background location is encoded into the mode of the foreground
+ // location
+ if (isPermissionGranted(packageName, ACCESS_COARSE_LOCATION)) {
+ setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_ALLOWED);
+ } else {
+ setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
+ }
+ } else if (permission.equals(ACCESS_COARSE_LOCATION)) {
+ // The app-op for location depends on the state of the bg location
+ if (isPermissionGranted(packageName, ACCESS_BACKGROUND_LOCATION)) {
+ setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_ALLOWED);
+ } else {
+ setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
+ }
+ } else if (permission.equals(PACKAGE_USAGE_STATS)) {
+ setAppOpByName(packageName, OPSTR_GET_USAGE_STATS, MODE_ALLOWED);
+ } else if (permissionToOp(permission) != null) {
+ setAppOp(packageName, permission, MODE_ALLOWED);
+ }
+ }
+
+ /**
+ * Revoke a permission from an app.
+ *
+ * <p>This correctly handles pre-M apps by setting the app-ops.
+ * <p>This also correctly handles the location background permission, but does not handle any
+ * other background permission
+ *
+ * @param packageName The app that should have the permission revoked
+ * @param permission The permission to revoke
+ */
+ public static void revokePermission(@NonNull String packageName, @NonNull String permission)
+ throws Exception {
+ sUiAutomation.revokeRuntimePermission(packageName, permission);
+
+ if (permission.equals(ACCESS_BACKGROUND_LOCATION)) {
+ // The app-op for background location is encoded into the mode of the foreground
+ // location
+ if (isGranted(packageName, ACCESS_COARSE_LOCATION)) {
+ setAppOp(packageName, ACCESS_COARSE_LOCATION, MODE_FOREGROUND);
+ }
+ } else if (permission.equals(PACKAGE_USAGE_STATS)) {
+ setAppOpByName(packageName, OPSTR_GET_USAGE_STATS, MODE_IGNORED);
+ } else if (permissionToOp(permission) != null) {
+ setAppOp(packageName, permission, MODE_IGNORED);
+ }
+ }
+
+ /**
+ * Clear permission state (not app-op state) of package.
+ *
+ * @param packageName Package to clear
+ */
+ public static void clearAppState(@NonNull String packageName) {
+ runShellCommand("pm clear --user current " + packageName);
+ }
+
+ /**
+ * Get all the flags of a permission.
+ *
+ * @param packageName Package the permission belongs to
+ * @param permission Name of the permission
+ *
+ * @return Permission flags
+ */
+ public static int getAllPermissionFlags(@NonNull String packageName,
+ @NonNull String permission) {
+ try {
+ return callWithShellPermissionIdentity(
+ () -> sContext.getPackageManager().getPermissionFlags(permission, packageName,
+ UserHandle.getUserHandleForUid(Process.myUid())),
+ GRANT_RUNTIME_PERMISSIONS);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Get the flags of a permission.
+ *
+ * @param packageName Package the permission belongs to
+ * @param permission Name of the permission
+ *
+ * @return Permission flags
+ */
+ public static int getPermissionFlags(@NonNull String packageName, @NonNull String permission) {
+ return getAllPermissionFlags(packageName, permission) & TESTED_FLAGS;
+ }
+
+ /**
+ * Set the flags of a permission.
+ *
+ * @param packageName Package the permission belongs to
+ * @param permission Name of the permission
+ * @param mask Mask of permissions to set
+ * @param flags Permissions to set
+ */
+ public static void setPermissionFlags(@NonNull String packageName, @NonNull String permission,
+ int mask, int flags) {
+ runWithShellPermissionIdentity(
+ () -> sContext.getPackageManager().updatePermissionFlags(permission, packageName,
+ mask, flags, UserHandle.getUserHandleForUid(Process.myUid())),
+ GRANT_RUNTIME_PERMISSIONS, ADJUST_RUNTIME_PERMISSIONS_POLICY);
+ }
+
+ /**
+ * Get all permissions an app requests. This includes the split permissions.
+ *
+ * @param packageName The package that requests the permissions.
+ *
+ * @return The permissions requested by the app
+ */
+ public static @NonNull List<String> getPermissions(@NonNull String packageName)
+ throws Exception {
+ PackageInfo appInfo = sContext.getPackageManager().getPackageInfo(packageName,
+ GET_PERMISSIONS);
+
+ return Arrays.asList(appInfo.requestedPermissions);
+ }
+
+ /**
+ * Get all runtime permissions that an app requests. This includes the split permissions.
+ *
+ * @param packageName The package that requests the permissions.
+ *
+ * @return The runtime permissions requested by the app
+ */
+ public static @NonNull List<String> getRuntimePermissions(@NonNull String packageName)
+ throws Exception {
+ ArrayList<String> runtimePermissions = new ArrayList<>();
+
+ for (String perm : getPermissions(packageName)) {
+ PermissionInfo info = sContext.getPackageManager().getPermissionInfo(perm, 0);
+ if ((info.getProtection() & PROTECTION_DANGEROUS) != 0) {
+ runtimePermissions.add(perm);
+ }
+ }
+
+ return runtimePermissions;
+ }
+
+ /**
+ * Reset permission controller state & re-schedule the job.
+ */
+ public static void resetPermissionControllerJob(@NonNull UiAutomation automation,
+ @NonNull String packageName, int jobId, long timeout, @NonNull String intentAction,
+ @NonNull String onBootReceiver) throws Exception {
+ clearAppState(packageName);
+ awaitJobUntilRequestedState(packageName, jobId, timeout, automation, "unknown");
+ scheduleJob(automation, packageName, jobId, timeout, intentAction, onBootReceiver);
+
+ runShellCommand("cmd jobscheduler reset-execution-quota -u "
+ + Process.myUserHandle().getIdentifier() + " " + packageName);
+ runShellCommand("cmd jobscheduler reset-schedule-quota");
+ }
+
+ /**
+ * schedules a job for the privacy signal in Permission Controller
+ */
+ public static void scheduleJob(@NonNull UiAutomation automation,
+ @NonNull String packageName, int jobId, long timeout, @NonNull String intentAction,
+ @NonNull String broadcastReceiver) throws Exception {
+ long startTime = System.currentTimeMillis();
+ String jobStatus = "";
+ simulateReboot(packageName, intentAction, broadcastReceiver);
+
+ while ((System.currentTimeMillis() - startTime) < timeout
+ && !jobStatus.contains("waiting")) {
+ String cmd =
+ "cmd jobscheduler get-job-state -u " + Process.myUserHandle().getIdentifier()
+ + " " + packageName + " " + jobId;
+ jobStatus = runShellCommand(automation, cmd).trim();
+ Log.v(LOG_TAG, "Job: " + jobId + ", job status " + jobStatus);
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // ignore interrupt
+ }
+ }
+ if (!jobStatus.contains("waiting")) {
+ throw new IllegalStateException("The job didn't get scheduled in time.");
+ }
+ }
+
+ private static void simulateReboot(@NonNull String packageName, @NonNull String intentAction,
+ @NonNull String broadcastReceiver) {
+ Intent jobSetupReceiverIntent = new Intent(intentAction);
+ jobSetupReceiverIntent.setPackage(packageName);
+ jobSetupReceiverIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+
+ // Query for the setup broadcast receiver
+ List<ResolveInfo> resolveInfos =
+ sContext.getPackageManager().queryBroadcastReceivers(jobSetupReceiverIntent, 0);
+
+ if (resolveInfos.size() > 0) {
+ sContext.sendBroadcast(jobSetupReceiverIntent);
+ } else {
+ Intent intent = new Intent();
+ intent.setClassName(packageName, broadcastReceiver);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setPackage(packageName);
+ sContext.sendBroadcast(intent);
+ }
+ waitForBroadcastDispatch(intentAction);
+ }
+}
diff --git a/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
new file mode 100644
index 000000000..48ccbe79f
--- /dev/null
+++ b/tests/cts/permission/permissionTestUtilLib/src/android/permission/cts/TestUtils.java
@@ -0,0 +1,205 @@
+/*
+ * 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.permission.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import android.app.UiAutomation;
+import android.os.Process;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Assert;
+
+/** Common test utilities */
+public class TestUtils {
+ private static final String LOG_TAG = TestUtils.class.getSimpleName();
+
+ /**
+ * A {@link java.util.concurrent.Callable} that can throw a {@link Throwable}
+ */
+ public interface ThrowingCallable<T> {
+ T call() throws Throwable;
+ }
+
+ /**
+ * A {@link Runnable} that can throw a {@link Throwable}
+ */
+ public interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+
+ /**
+ * Make sure that a {@link ThrowingRunnable} finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingRunnable} to run.
+ * @param timeout the maximum time to wait
+ */
+ public static void ensure(@NonNull ThrowingRunnable r, long timeout) throws Throwable {
+ ensure(() -> {
+ r.run();
+ return 0;
+ }, timeout);
+ }
+
+ /**
+ * Make sure that a {@link ThrowingCallable} finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingCallable} to run.
+ * @param timeout the maximum time to wait
+ * @return the return value from the callable
+ * @throws NullPointerException If the return value never becomes non-null
+ */
+ public static <T> T ensure(@NonNull ThrowingCallable<T> r, long timeout) throws Throwable {
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ T res = r.call();
+ if (res == null) {
+ throw new NullPointerException("No result");
+ }
+
+ if (System.currentTimeMillis() - start < timeout) {
+ Thread.sleep(500);
+ } else {
+ return res;
+ }
+ }
+ }
+
+ /**
+ * Make sure that a {@link ThrowingRunnable} eventually finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingRunnable} to run.
+ * @param timeout the maximum time to wait
+ */
+ public static void eventually(@NonNull ThrowingRunnable r, long timeout) throws Throwable {
+ eventually(() -> {
+ r.run();
+ return 0;
+ }, timeout);
+ }
+
+ /**
+ * Make sure that a {@link ThrowingCallable} eventually finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingCallable} to run.
+ * @param timeout the maximum time to wait
+ * @return the return value from the callable
+ * @throws NullPointerException If the return value never becomes non-null
+ */
+ public static <T> T eventually(@NonNull ThrowingCallable<T> r, long timeout) throws Throwable {
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ try {
+ T res = r.call();
+ if (res == null) {
+ throw new NullPointerException("No result");
+ }
+
+ return res;
+ } catch (Throwable e) {
+ if (System.currentTimeMillis() - start < timeout) {
+ Log.d(LOG_TAG, "Ignoring exception, occurred within valid wait time", e);
+
+ Thread.sleep(500);
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Run the job and then wait for completion
+ */
+ public static void runJobAndWaitUntilCompleted(
+ String packageName,
+ int jobId, long timeout) {
+ runJobAndWaitUntilCompleted(packageName, jobId, timeout,
+ InstrumentationRegistry.getInstrumentation().getUiAutomation());
+ }
+
+ /**
+ * Run the job and then wait for completion
+ */
+ public static void runJobAndWaitUntilCompleted(
+ String packageName,
+ int jobId,
+ long timeout,
+ UiAutomation automation) {
+ String runJobCmd = "cmd jobscheduler run -u " + Process.myUserHandle().getIdentifier()
+ + " -f " + packageName + " " + jobId;
+ try {
+ String result = runShellCommand(automation, runJobCmd);
+ Log.v(LOG_TAG, "jobscheduler run job command output: " + result);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ // waiting state is expected after completion for the periodic jobs.
+ awaitJobUntilRequestedState(packageName, jobId, timeout, automation, "waiting");
+ }
+
+ public static void awaitJobUntilRequestedState(
+ String packageName,
+ int jobId,
+ long timeout,
+ UiAutomation automation,
+ String requestedState) {
+ String statusCmd = "cmd jobscheduler get-job-state -u "
+ + Process.myUserHandle().getIdentifier() + " " + packageName + " " + jobId;
+ try {
+ eventually(() -> {
+ String jobState = runShellCommand(automation, statusCmd).trim();
+ Assert.assertTrue("The job doesn't have requested state " + requestedState
+ + " yet, current state: " + jobState, jobState.startsWith(requestedState));
+ }, timeout);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void awaitJobUntilRequestedState(
+ String packageName,
+ int jobId,
+ long timeout,
+ UiAutomation automation,
+ String requestedState1,
+ String requestedState2) {
+ String statusCmd = "cmd jobscheduler get-job-state -u "
+ + Process.myUserHandle().getIdentifier() + " " + packageName + " " + jobId;
+ try {
+ eventually(() -> {
+ String jobState = runShellCommand(automation, statusCmd).trim();
+ boolean jobInEitherRequestedState = jobState.startsWith(requestedState1)
+ || jobState.startsWith(requestedState2);
+ Assert.assertTrue("The job doesn't have requested state "
+ + "(" + requestedState1 + " or " + requestedState2 + ")"
+ + " yet, current state: " + jobState, jobInEitherRequestedState);
+ }, timeout);
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/tests/cts/permission/res/drawable/robot.png b/tests/cts/permission/res/drawable/robot.png
new file mode 100644
index 000000000..8a9e6984b
--- /dev/null
+++ b/tests/cts/permission/res/drawable/robot.png
Binary files differ
diff --git a/tests/cts/permission/res/values/strings.xml b/tests/cts/permission/res/values/strings.xml
new file mode 100644
index 000000000..bebb179ec
--- /dev/null
+++ b/tests/cts/permission/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="perm_b">Permission B</string>
+ <string name="perm_c">Permission C</string>
+ <string name="perm_group_b">Permission group B</string>
+ <string name="perm_group_c">Permission group B</string>
+</resources>
diff --git a/tests/cts/permission/res/xml/test_accessibilityservice.xml b/tests/cts/permission/res/xml/test_accessibilityservice.xml
new file mode 100644
index 000000000..fa87e2e0f
--- /dev/null
+++ b/tests/cts/permission/res/xml/test_accessibilityservice.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accessibilityEventTypes="typeAllMask"
+ android:accessibilityFeedbackType="feedbackGeneric"
+ android:canRetrieveWindowContent="true"
+ android:accessibilityFlags="flagDefault"
+ android:notificationTimeout="0" />
diff --git a/tests/cts/permission/sdk28/Android.bp b/tests/cts/permission/sdk28/Android.bp
new file mode 100644
index 000000000..3043c9329
--- /dev/null
+++ b/tests/cts/permission/sdk28/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionTestCasesSdk28",
+ defaults: ["cts_defaults"],
+ sdk_version: "28",
+ srcs: ["src/**/*.java"],
+ static_libs: ["ctstestrunner-axt"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permission/sdk28/AndroidManifest.xml b/tests/cts/permission/sdk28/AndroidManifest.xml
new file mode 100644
index 000000000..1714052f7
--- /dev/null
+++ b/tests/cts/permission/sdk28/AndroidManifest.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.sdk28">
+
+ <uses-sdk android:minSdkVersion="3"
+ android:targetSdkVersion="28"
+ android:maxSdkVersion="28"/>
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <activity android:name="android.permission.cts.PermissionStubActivity"
+ android:label="PermissionStubActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <!--
+ The CTS stubs package cannot be used as the target application here,
+ since that requires many permissions to be set. Instead, specify this
+ package itself as the target and include any stub activities needed.
+
+ This test package uses the default InstrumentationTestRunner, because
+ the InstrumentationCtsTestRunner is only available in the stubs
+ package. That runner cannot be added to this package either, since it
+ relies on hidden APIs.
+ -->
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permission.cts.sdk28"
+ android:label="CTS tests of legacy android permissions as of API 28">
+ </instrumentation>
+
+</manifest>
diff --git a/tests/cts/permission/sdk28/AndroidTest.xml b/tests/cts/permission/sdk28/AndroidTest.xml
new file mode 100644
index 000000000..391142964
--- /dev/null
+++ b/tests/cts/permission/sdk28/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+<configuration description="Config for CTS Permission test cases for TargetSdk 28">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="not-shardable" value="true" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionTestCasesSdk28.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permission.cts.sdk28" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/tests/cts/permission/sdk28/OWNERS b/tests/cts/permission/sdk28/OWNERS
new file mode 100644
index 000000000..98dc09e9e
--- /dev/null
+++ b/tests/cts/permission/sdk28/OWNERS
@@ -0,0 +1 @@
+# Bug component: 137825
diff --git a/tests/cts/permission/sdk28/TEST_MAPPING b/tests/cts/permission/sdk28/TEST_MAPPING
new file mode 100644
index 000000000..b98bbaf43
--- /dev/null
+++ b/tests/cts/permission/sdk28/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsPermissionTestCasesSdk28"
+ }
+ ]
+}
diff --git a/tests/cts/permission/sdk28/res/values/strings.xml b/tests/cts/permission/sdk28/res/values/strings.xml
new file mode 100644
index 000000000..9cc70f91a
--- /dev/null
+++ b/tests/cts/permission/sdk28/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sdk28">SDK Level 28</string>
+</resources>
diff --git a/tests/cts/permission/sdk28/src/android/permission/cts/sdk28/RequestLocation.java b/tests/cts/permission/sdk28/src/android/permission/cts/sdk28/RequestLocation.java
new file mode 100644
index 000000000..8ba39cdfe
--- /dev/null
+++ b/tests/cts/permission/sdk28/src/android/permission/cts/sdk28/RequestLocation.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.permission.cts.sdk28;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.telephony.NeighboringCellInfo;
+import android.telephony.TelephonyManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class RequestLocation {
+
+ private TelephonyManager mTelephonyManager;
+ private boolean mHasTelephony;
+
+ @Before
+ public void setUp() throws Exception {
+ mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY);
+ mTelephonyManager = (TelephonyManager) getContext().getSystemService(
+ Context.TELEPHONY_SERVICE);
+ assertNotNull(mTelephonyManager);
+ }
+
+ /**
+ * Verify that a SecurityException is thrown when an app targeting SDK 28
+ * lacks the coarse location permission.
+ */
+ @Test
+ public void testGetNeighboringCellInfo() {
+ if (!mHasTelephony) return;
+ try {
+ List<NeighboringCellInfo> cellInfos = mTelephonyManager.getNeighboringCellInfo();
+ if (cellInfos != null && !cellInfos.isEmpty()) {
+ fail("Meaningful information returned from getNeighboringCellInfo!");
+ }
+ } catch (SecurityException expected) {
+ }
+ }
+
+ private static Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt b/tests/cts/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
new file mode 100644
index 000000000..e7bad2b05
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/AccessibilityPrivacySourceTest.kt
@@ -0,0 +1,358 @@
+/*
+ * 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.permission.cts
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService
+import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule
+import android.app.ActivityOptions
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.content.ComponentName
+import android.content.Context
+import android.os.Build
+import android.os.Process
+import android.permission.cts.CtsNotificationListenerServiceUtils.assertEmptyNotification
+import android.permission.cts.CtsNotificationListenerServiceUtils.assertNotificationExist
+import android.permission.cts.CtsNotificationListenerServiceUtils.cancelNotification
+import android.permission.cts.CtsNotificationListenerServiceUtils.cancelNotifications
+import android.permission.cts.CtsNotificationListenerServiceUtils.getNotification
+import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueDoesNotExist
+import android.permission.cts.SafetyCenterUtils.assertSafetyCenterIssueExist
+import android.permission.cts.SafetyCenterUtils.assertSafetyCenterStarted
+import android.permission.cts.SafetyCenterUtils.deleteDeviceConfigPrivacyProperty
+import android.permission.cts.SafetyCenterUtils.deviceSupportsSafetyCenter
+import android.permission.cts.SafetyCenterUtils.setDeviceConfigPrivacyProperty
+import android.platform.test.annotations.AppModeFull
+import android.platform.test.rule.ScreenRecordRule
+import android.provider.DeviceConfig
+import android.safetycenter.SafetyCenterManager
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.modules.utils.build.SdkLevel
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assume
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@AppModeFull(
+ reason =
+ "Cannot set system settings as instant app. Also we never show an accessibility " +
+ "notification for instant apps."
+)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@ScreenRecordRule.ScreenRecord
+@FlakyTest
+class AccessibilityPrivacySourceTest {
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = instrumentation.targetContext
+ private val permissionControllerPackage = context.packageManager.permissionControllerPackageName
+ private val accessibilityTestService =
+ ComponentName(context, AccessibilityTestService::class.java).flattenToString()
+ private val safetyCenterIssueId = "accessibility_$accessibilityTestService"
+ private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)
+
+ @get:Rule val screenRecordRule = ScreenRecordRule(false, false)
+
+ @get:Rule
+ val mAccessibilityServiceRule =
+ InstrumentedAccessibilityServiceTestRule(AccessibilityTestService::class.java, false)
+
+ @get:Rule
+ val deviceConfigSafetyCenterEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_CENTER_ENABLED,
+ true.toString()
+ )
+
+ @get:Rule
+ val deviceConfigA11ySourceEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ ACCESSIBILITY_SOURCE_ENABLED,
+ true.toString()
+ )
+
+ @get:Rule
+ val deviceConfigA11yListenerDisabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ ACCESSIBILITY_LISTENER_ENABLED,
+ false.toString()
+ )
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(deviceSupportsSafetyCenter(context))
+ InstrumentedAccessibilityService.disableAllServices()
+ runShellCommand("input keyevent KEYCODE_WAKEUP")
+ resetPermissionController()
+ // Bypass battery saving restrictions
+ runShellCommand(
+ "cmd tare set-vip " +
+ "${Process.myUserHandle().identifier} $permissionControllerPackage true"
+ )
+ cancelNotifications(permissionControllerPackage)
+ assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ runWithShellPermissionIdentity { safetyCenterManager?.clearAllSafetySourceDataForTests() }
+ assertSafetyCenterIssueDoesNotExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID
+ )
+ }
+
+ @After
+ fun cleanup() {
+ cancelNotifications(permissionControllerPackage)
+ // Reset battery saving restrictions
+ runShellCommand(
+ "cmd tare set-vip " +
+ "${Process.myUserHandle().identifier} $permissionControllerPackage default"
+ )
+ runWithShellPermissionIdentity { safetyCenterManager?.clearAllSafetySourceDataForTests() }
+ }
+
+ @Test
+ fun testJobSendsNotification() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ }
+
+ @Test
+ fun testJobSendsNotificationOnEnable() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString())
+ cancelNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ InstrumentedAccessibilityService.disableAllServices()
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString())
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS, "0")
+
+ // enable service again and verify a notification
+ try {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ } finally {
+ deleteDeviceConfigPrivacyProperty(ACCESSIBILITY_JOB_INTERVAL_MILLIS)
+ }
+ }
+
+ @Test
+ fun testJobSendsIssuesToSafetyCenter() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertSafetyCenterIssueExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID
+ )
+ }
+
+ @Test
+ fun testJobDoesNotSendNotificationInSecondRunForSameService() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+
+ cancelNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+
+ runJobAndWaitUntilCompleted()
+ assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ }
+
+ @Test
+ fun testAccessibilityListenerSendsIssueToSafetyCenter() {
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, true.toString())
+ try {
+ val automation = getAutomation()
+ mAccessibilityServiceRule.enableService()
+ TestUtils.eventually(
+ {
+ assertSafetyCenterIssueExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID,
+ automation
+ )
+ },
+ TIMEOUT_MILLIS
+ )
+ automation.destroy()
+ } finally {
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_LISTENER_ENABLED, false.toString())
+ }
+ }
+
+ @Test
+ fun testJobWithDisabledServiceDoesNotSendNotification() {
+ runJobAndWaitUntilCompleted()
+ assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ }
+
+ @Test
+ fun testJobWithDisabledServiceDoesNotSendIssueToSafetyCenter() {
+ runJobAndWaitUntilCompleted()
+ assertSafetyCenterIssueDoesNotExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID
+ )
+ }
+
+ @Test
+ fun testJobWithAccessibilityFeatureDisabledDoesNotSendNotification() {
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_SOURCE_ENABLED, false.toString())
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ }
+
+ @Test
+ fun testJobWithAccessibilityFeatureDisabledDoesNotSendIssueToSafetyCenter() {
+ setDeviceConfigPrivacyProperty(ACCESSIBILITY_SOURCE_ENABLED, false.toString())
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertSafetyCenterIssueDoesNotExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID
+ )
+ }
+
+ @Test
+ fun testJobWithSafetyCenterDisabledDoesNotSendNotification() {
+ setDeviceConfigPrivacyProperty(SAFETY_CENTER_ENABLED, false.toString())
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertEmptyNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ }
+
+ @Test
+ fun testJobWithSafetyCenterDisabledDoesNotSendIssueToSafetyCenter() {
+ setDeviceConfigPrivacyProperty(SAFETY_CENTER_ENABLED, false.toString())
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertSafetyCenterIssueDoesNotExist(
+ SC_ACCESSIBILITY_SOURCE_ID,
+ safetyCenterIssueId,
+ SC_ACCESSIBILITY_ISSUE_TYPE_ID
+ )
+ }
+
+ @Test
+ fun testNotificationClickOpenSafetyCenter() {
+ mAccessibilityServiceRule.enableService()
+ runJobAndWaitUntilCompleted()
+ assertNotificationExist(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ val statusBarNotification =
+ getNotification(permissionControllerPackage, ACCESSIBILITY_NOTIFICATION_ID)
+ Assert.assertNotNull(statusBarNotification)
+ val contentIntent = statusBarNotification!!.notification.contentIntent
+ if (SdkLevel.isAtLeastU()) {
+ val options =
+ ActivityOptions.makeBasic()
+ .setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+ )
+ contentIntent.send(
+ /* context = */ null,
+ /* code = */ 0,
+ /* intent = */ null,
+ /* onFinished = */ null,
+ /* handler = */ null,
+ /* requiredPermission = */ null,
+ /* options = */ options.toBundle()
+ )
+ } else {
+ contentIntent.send()
+ }
+ assertSafetyCenterStarted()
+ }
+
+ private fun getAutomation(): UiAutomation {
+ return instrumentation.getUiAutomation(
+ UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
+ )
+ }
+
+ private fun runJobAndWaitUntilCompleted() {
+ TestUtils.runJobAndWaitUntilCompleted(
+ permissionControllerPackage,
+ ACCESSIBILITY_JOB_ID,
+ TIMEOUT_MILLIS,
+ getAutomation()
+ )
+ }
+
+ /** Reset the permission controllers state. */
+ @Throws(Throwable::class)
+ private fun resetPermissionController() {
+ PermissionUtils.resetPermissionControllerJob(
+ getAutomation(),
+ permissionControllerPackage,
+ ACCESSIBILITY_JOB_ID,
+ 45000,
+ ACTION_SET_UP_ACCESSIBILITY_CHECK,
+ AccessibilityOnBootReceiver
+ )
+ }
+
+ companion object {
+ private const val SC_ACCESSIBILITY_SOURCE_ID = "AndroidAccessibility"
+ private const val ACCESSIBILITY_SOURCE_ENABLED = "sc_accessibility_source_enabled"
+ private const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
+ private const val ACCESSIBILITY_LISTENER_ENABLED = "sc_accessibility_listener_enabled"
+ private const val ACCESSIBILITY_JOB_INTERVAL_MILLIS = "sc_accessibility_job_interval_millis"
+
+ private const val ACCESSIBILITY_JOB_ID = 6
+ private const val ACCESSIBILITY_NOTIFICATION_ID = 4
+ private const val TIMEOUT_MILLIS: Long = 10000
+
+ private const val SC_ACCESSIBILITY_ISSUE_TYPE_ID = "accessibility_privacy_issue"
+
+ private const val AccessibilityOnBootReceiver =
+ "com.android.permissioncontroller.privacysources.AccessibilityOnBootReceiver"
+ private const val ACTION_SET_UP_ACCESSIBILITY_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_ACCESSIBILITY_CHECK"
+
+ @get:ClassRule
+ @JvmStatic
+ val ctsNotificationListenerHelper =
+ CtsNotificationListenerHelperRule(
+ InstrumentationRegistry.getInstrumentation().targetContext
+ )
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/AccessibilityTestService.kt b/tests/cts/permission/src/android/permission/cts/AccessibilityTestService.kt
new file mode 100644
index 000000000..9f5e3f172
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/AccessibilityTestService.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.permission.cts
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService
+
+/**
+ * Test Accessibility Service
+ */
+class AccessibilityTestService : InstrumentedAccessibilityService()
diff --git a/tests/cts/permission/src/android/permission/cts/ActivityPermissionRationaleTest.java b/tests/cts/permission/src/android/permission/cts/ActivityPermissionRationaleTest.java
new file mode 100644
index 000000000..47f011a34
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ActivityPermissionRationaleTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.Manifest;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@AppModeFull(reason = "Tests properties of other app. Instant apps cannot interact with other apps")
+@RunWith(AndroidJUnit4ClassRunner.class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class ActivityPermissionRationaleTest {
+ private static final String APK =
+ "/data/local/tmp/cts-permission/CtsAppThatRunsRationaleTests.apk";
+ private static final String PACKAGE_NAME = "android.permission.cts.appthatrunsrationaletests";
+ private static final String PERMISSION_NAME = Manifest.permission.READ_CONTACTS;
+ private static final String CALLBACK_KEY = "testactivitycallback";
+ private static final String RESULT_KEY = "testactivityresult";
+ private static final int TIMEOUT = 5000;
+
+ private static Context sContext = InstrumentationRegistry.getInstrumentation().getContext();
+ private static UiAutomation sUiAuto =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ @BeforeClass
+ public static void setUp() {
+ runShellCommandOrThrow("pm install -r " + APK);
+ int flag = PackageManager.FLAG_PERMISSION_USER_SET;
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME, flag, flag);
+ }
+
+ @AfterClass
+ public static void unInstallApp() {
+ runShellCommand("pm uninstall " + PACKAGE_NAME);
+ }
+
+ private void assertAppShowRationaleIs(boolean expected) throws Exception {
+ CompletableFuture<Boolean> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) ->
+ callbackReturn.complete(result.getBoolean(RESULT_KEY)));
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".TestActivity"));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(CALLBACK_KEY, cb);
+
+ sContext.startActivity(intent);
+ assertThat(callbackReturn.get(TIMEOUT, TimeUnit.MILLISECONDS)).isEqualTo(expected);
+ }
+
+ @Before
+ public void clearData() {
+ runShellCommand("pm clear --user " + sContext.getUserId()
+ + " android.permission.cts.appthatrunsrationaletests");
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME,
+ PackageManager.FLAG_PERMISSION_POLICY_FIXED, 0);
+ }
+
+ @Test
+ public void permissionGrantedNoRationale() throws Exception {
+ sUiAuto.grantRuntimePermission(PACKAGE_NAME, PERMISSION_NAME);
+
+ assertAppShowRationaleIs(false);
+ }
+
+ @Test
+ public void policyFixedNoRationale() throws Exception {
+ int flags = PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME, flags, flags);
+
+ assertAppShowRationaleIs(false);
+ }
+
+ @Test
+ public void userFixedNoRationale() throws Exception {
+ int flags = PackageManager.FLAG_PERMISSION_USER_FIXED;
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME, flags, flags);
+
+ assertAppShowRationaleIs(false);
+ }
+
+ @Test
+ public void notUserSetNoRationale() throws Exception {
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME,
+ PackageManager.FLAG_PERMISSION_USER_SET, 0);
+
+ assertAppShowRationaleIs(false);
+ }
+
+ @Test
+ public void userSetNeedRationale() throws Exception {
+ int flags = PackageManager.FLAG_PERMISSION_USER_SET;
+ PermissionUtils.setPermissionFlags(PACKAGE_NAME, PERMISSION_NAME, flags, flags);
+
+ assertAppShowRationaleIs(true);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/AppIdleStatePermissionTest.java b/tests/cts/permission/src/android/permission/cts/AppIdleStatePermissionTest.java
new file mode 100644
index 000000000..bba996366
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/AppIdleStatePermissionTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static org.junit.Assert.fail;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * Build, install and run tests with following command:
+ * atest AppIdleStatePermissionTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AppIdleStatePermissionTest {
+
+ /**
+ * Verify that the {@link android.Manifest.permission#CHANGE_APP_IDLE_STATE}
+ * permission is only held by at most one package.
+ */
+ @Test
+ public void testChangeAppIdleStatePermission() throws Exception {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[]{
+ android.Manifest.permission.CHANGE_APP_IDLE_STATE
+ }, PackageManager.MATCH_SYSTEM_ONLY);
+
+ int count = 0;
+ String pkgNames = "";
+ for (PackageInfo pkg : holding) {
+ int uid = pm.getApplicationInfo(pkg.packageName, 0).uid;
+ if (UserHandle.isApp(uid)) {
+ pkgNames += pkg.packageName + "\n";
+ count++;
+ }
+ }
+ if (count > 1) {
+ fail("Only one app may hold the CHANGE_APP_IDLE_STATE permission; found packages: \n"
+ + pkgNames);
+ }
+ }
+
+ /**
+ * Verify that the {@link android.Manifest.permission#CHANGE_APP_LAUNCH_TIME_ESTIMATE}
+ * permission is only held by at most one package.
+ */
+ @Test
+ public void testChangeAppLaunchEstimatePermission() throws Exception {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[]{
+ android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE
+ }, PackageManager.MATCH_SYSTEM_ONLY);
+
+ int count = 0;
+ String pkgNames = "";
+ for (PackageInfo pkg : holding) {
+ int uid = pm.getApplicationInfo(pkg.packageName, 0).uid;
+ if (UserHandle.isApp(uid)) {
+ pkgNames += pkg.packageName + "\n";
+ count++;
+ }
+ }
+ if (count > 1) {
+ fail("Only one app may hold the CHANGE_APP_LAUNCH_TIME_ESTIMATE permission;"
+ + " found packages: \n" + pkgNames);
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java b/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
new file mode 100644
index 000000000..294896d97
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+* Test that protected AppWidgetManager APIs cannot be called without permissions
+*/
+public class AppWidgetManagerPermissionTest extends AndroidTestCase {
+
+ private AppWidgetManager mAppWidgetManager = null;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAppWidgetManager = AppWidgetManager.getInstance(getContext());
+ }
+
+ /**
+ * Verify that calling
+ * {@link AppWidgetManager#bindAppWidgetId(int, android.content.ComponentName)}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#BIND_APP_WIDGET}.
+ */
+ @SmallTest
+ public void testBindAppWidget() {
+ if (!getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
+ return;
+ }
+ assertNotNull(mAppWidgetManager);
+
+ try {
+ final boolean bound = mAppWidgetManager.bindAppWidgetIdIfAllowed(1,
+ new ComponentName(mContext, "foo"));
+ assertFalse("Was able to call bindAppWidgetId", bound);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java
new file mode 100644
index 000000000..004f8bc8c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionButtonLabelTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BackgroundPermissionButtonLabelTest {
+
+ // Name of the resource which provides background permission button string
+ public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
+ "app_permission_button_allow_always";
+
+ private final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private final String mPermissionController =
+ mContext.getPackageManager().getPermissionControllerPackageName();
+
+ @Test
+ public void testBackgroundPermissionButtonLabel() {
+ try {
+ Context permissionControllerContext =
+ mContext.createPackageContext(mPermissionController, 0);
+ int stringId = permissionControllerContext.getResources().getIdentifier(
+ APP_PERMISSION_BUTTON_ALLOW_ALWAYS, "string",
+ "com.android.permissioncontroller");
+
+ Assert.assertEquals(mContext.getPackageManager().getBackgroundPermissionOptionLabel(),
+ permissionControllerContext.getString(stringId));
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+}
diff --git a/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java
new file mode 100644
index 000000000..f3f47631c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/BackgroundPermissionsTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+import static android.content.pm.PermissionInfo.PROTECTION_INTERNAL;
+import static android.permission.cts.PermissionUtils.getAppOp;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.AppOpsManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.AppModeFull;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BackgroundPermissionsTest {
+ private static final String LOG_TAG = BackgroundPermissionsTest.class.getSimpleName();
+
+ /** The package name of all apps used in the test */
+ private static final String APP_PKG = "android.permission.cts.appthatrequestpermission";
+
+ private static final String TMP_DIR = "/data/local/tmp/cts-permission/";
+ private static final String APK_LOCATION_BACKGROUND_29 =
+ TMP_DIR + "CtsAppThatRequestsLocationAndBackgroundPermission29.apk";
+ private static final String APK_LOCATION_29v4 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission29v4.apk";
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private static final UiAutomation sUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ @After
+ public void uninstallTestApp() {
+ uninstallApp(APP_PKG);
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages")
+ public void verifybackgroundPermissionsProperties() throws Exception {
+ PackageInfo pkg = sContext.getPackageManager().getPackageInfo(
+ "android", PackageManager.GET_PERMISSIONS);
+ ArrayMap<String, String> potentialBackgroundPermissionsToGroup = new ArrayMap<>();
+
+ int numPermissions = pkg.permissions.length;
+ for (int i = 0; i < numPermissions; i++) {
+ PermissionInfo permission = pkg.permissions[i];
+
+ // background permissions must be dangerous or ungrantable or role
+ if ((permission.getProtection() & PROTECTION_DANGEROUS) != 0
+ || (permission.getProtection() == PROTECTION_INTERNAL
+ && (permission.getProtectionFlags() == 0
+ || permission.getProtectionFlags() == PermissionInfo.PROTECTION_FLAG_ROLE))) {
+ potentialBackgroundPermissionsToGroup.put(permission.name, permission.group);
+ }
+ }
+
+ for (int i = 0; i < numPermissions; i++) {
+ PermissionInfo permission = pkg.permissions[i];
+ String backgroundPermissionName = permission.backgroundPermission;
+
+ if (backgroundPermissionName != null) {
+ Log.i(LOG_TAG, permission.name + "->" + backgroundPermissionName);
+
+ // foreground permissions must be dangerous
+ assertNotEquals(0, permission.getProtection() & PROTECTION_DANGEROUS);
+
+ // All foreground permissions need an app op
+ assertNotNull(AppOpsManager.permissionToOp(permission.name));
+
+ // the background permission must exist
+ assertTrue(potentialBackgroundPermissionsToGroup
+ .containsKey(backgroundPermissionName));
+ }
+ }
+ }
+
+ /**
+ * If a bg permission is lost during an upgrade, the app-op should downgrade to foreground
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpGetsDowngradedWhenBgPermIsNotRequestedAnymore() throws Exception {
+ install(APK_LOCATION_BACKGROUND_29);
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ install(APK_LOCATION_29v4);
+
+ eventually(() -> assertWithMessage("foreground app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_FOREGROUND));
+ }
+
+ /**
+ * Make sure location switch-op is set if no location access is granted.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfNoLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_IGNORED));
+ }
+
+ /**
+ * Make sure location switch-op is set if only coarse location is granted
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfOnlyCoarseLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_FOREGROUND));
+ }
+
+ /**
+ * Make sure location switch-op is set if coarse location with background access is granted.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfCoarseAndBgLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_ALLOWED));
+ }
+
+ /**
+ * Make sure location switch-op is set if only fine location is granted
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfOnlyFineLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_FINE_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ // Fine location uses background location to limit access
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_FOREGROUND));
+ }
+
+ /**
+ * Make sure location switch-op is set if fine location with background access is granted.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfFineAndBgLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_FINE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_ALLOWED));
+ }
+
+ /**
+ * Make sure location switch-op is set if fine and coarse location access is granted.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfFineAndCoarseLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_FINE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_FOREGROUND));
+ }
+
+ /**
+ * Make sure location switch-op is set if fine and coarse location with background access is
+ * granted.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them. Also instant apps are never updated, hence the test "
+ + "is useless.")
+ public void appOpIsSetIfFineCoarseAndBgLocPermIsGranted() {
+ install(APK_LOCATION_BACKGROUND_29);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_FINE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ // Wait until the system sets the app-op automatically
+ eventually(() -> assertWithMessage("loc app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_ALLOWED));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java b/tests/cts/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
new file mode 100644
index 000000000..42da8c830
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/BaseNotificationListenerCheckTest.java
@@ -0,0 +1,324 @@
+/*
+ * 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.permission.cts;
+
+import static android.os.Process.myUserHandle;
+import static android.permission.cts.TestUtils.eventually;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.app.NotificationManager;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.DeviceConfig;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+
+import java.util.List;
+
+/**
+ * Base test class used for {@code NotificationListenerCheckTest} and
+ * {@code NotificationListenerCheckWithSafetyCenterUnsupportedTest}
+ */
+public class BaseNotificationListenerCheckTest {
+ private static final String LOG_TAG = BaseNotificationListenerCheckTest.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ protected static final String TEST_APP_PKG =
+ "android.permission.cts.appthathasnotificationlistener";
+ private static final String TEST_APP_NOTIFICATION_SERVICE =
+ TEST_APP_PKG + ".CtsNotificationListenerService";
+ protected static final String TEST_APP_NOTIFICATION_LISTENER_APK =
+ "/data/local/tmp/cts-permission/CtsAppThatHasNotificationListener.apk";
+
+ private static final int NOTIFICATION_LISTENER_CHECK_JOB_ID = 4;
+
+ /**
+ * Device config property for whether notification listener check is enabled on the device
+ */
+ private static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED =
+ "notification_listener_check_enabled";
+
+ /**
+ * Device config property for time period in milliseconds after which current enabled
+ * notification
+ * listeners are queried
+ */
+ protected static final String PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
+ "notification_listener_check_interval_millis";
+
+ protected static final Long OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS =
+ SECONDS.toMillis(0);
+
+ private static final String ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_NOTIFICATION_LISTENER_CHECK";
+ private static final String NotificationListenerOnBootReceiver =
+ "com.android.permissioncontroller.privacysources.SetupPeriodicNotificationListenerCheck";
+
+ /**
+ * ID for notification shown by
+ * {@link com.android.permissioncontroller.privacysources.NotificationListenerCheck}.
+ */
+ public static final int NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID = 3;
+
+ protected static final long UNEXPECTED_TIMEOUT_MILLIS = 10000;
+ protected static final long ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS = 5000;
+
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private static final PackageManager sPackageManager = sContext.getPackageManager();
+ private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation();
+
+ private static final String PERMISSION_CONTROLLER_PKG = sContext.getPackageManager()
+ .getPermissionControllerPackageName();
+
+ private static List<ComponentName> sPreviouslyEnabledNotificationListeners;
+
+ // Override SafetyCenter enabled flag
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigSafetyCenterEnabled =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterUtils.PROPERTY_SAFETY_CENTER_ENABLED,
+ Boolean.toString(true));
+
+ // Override NlsCheck enabled flag
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigNlsCheckEnabled =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+ Boolean.toString(true));
+
+ // Override general notification interval from once every day to once ever 1 second
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigNlsCheckIntervalMillis =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS,
+ Long.toString(OVERRIDE_NOTIFICATION_LISTENER_CHECK_INTERVAL_MILLIS));
+
+ @Rule
+ public CtsNotificationListenerHelperRule ctsNotificationListenerHelper =
+ new CtsNotificationListenerHelperRule(sContext);
+
+ @BeforeClass
+ public static void beforeClassSetup() throws Exception {
+ // Bypass battery saving restrictions
+ runShellCommand("cmd tare set-vip "
+ + myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG + " true");
+ // Disallow any OEM enabled NLS
+ disallowPreexistingNotificationListeners();
+ }
+
+ @AfterClass
+ public static void afterClassTearDown() throws Throwable {
+ // Reset battery saving restrictions
+ runShellCommand("cmd tare set-vip "
+ + myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG + " default");
+ // Reallow any previously OEM allowed NLS
+ reallowPreexistingNotificationListeners();
+ }
+
+ protected static void setDeviceConfigPrivacyProperty(String propertyName, String value) {
+ runWithShellPermissionIdentity(() -> {
+ boolean valueWasSet = DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ /* name = */ propertyName,
+ /* value = */ value,
+ /* makeDefault = */ false);
+ if (!valueWasSet) {
+ throw new IllegalStateException("Could not set " + propertyName + " to " + value);
+ }
+ });
+ }
+
+ /**
+ * Enable or disable notification listener check
+ */
+ protected static void setNotificationListenerCheckEnabled(boolean enabled) {
+ setDeviceConfigPrivacyProperty(
+ PROPERTY_NOTIFICATION_LISTENER_CHECK_ENABLED,
+ /* value = */ String.valueOf(enabled));
+ }
+
+ /**
+ * Allow or disallow a {@link NotificationListenerService} component for the current user
+ *
+ * @param listenerComponent {@link NotificationListenerService} component to allow or disallow
+ */
+ private static void setNotificationListenerServiceAllowed(ComponentName listenerComponent,
+ boolean allowed) {
+ String command = " cmd notification " + (allowed ? "allow_listener " : "disallow_listener ")
+ + listenerComponent.flattenToString();
+ runShellCommand(command);
+ }
+
+ private static void disallowPreexistingNotificationListeners() {
+ runWithShellPermissionIdentity(() -> {
+ NotificationManager notificationManager =
+ sContext.getSystemService(NotificationManager.class);
+ sPreviouslyEnabledNotificationListeners =
+ notificationManager.getEnabledNotificationListeners();
+ });
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Found " + sPreviouslyEnabledNotificationListeners.size()
+ + " previously allowed notification listeners. Disabling before test run.");
+ }
+ for (ComponentName listener : sPreviouslyEnabledNotificationListeners) {
+ setNotificationListenerServiceAllowed(listener, false);
+ }
+ }
+
+ private static void reallowPreexistingNotificationListeners() {
+ if (DEBUG) {
+ Log.d(LOG_TAG, "Re-allowing " + sPreviouslyEnabledNotificationListeners.size()
+ + " previously allowed notification listeners found before test run.");
+ }
+ for (ComponentName listener : sPreviouslyEnabledNotificationListeners) {
+ setNotificationListenerServiceAllowed(listener, true);
+ }
+ }
+
+ protected void allowTestAppNotificationListenerService() {
+ setNotificationListenerServiceAllowed(
+ new ComponentName(TEST_APP_PKG, TEST_APP_NOTIFICATION_SERVICE), true);
+ }
+
+ protected void disallowTestAppNotificationListenerService() {
+ setNotificationListenerServiceAllowed(
+ new ComponentName(TEST_APP_PKG, TEST_APP_NOTIFICATION_SERVICE), false);
+ }
+
+ /**
+ * Force a run of the notification listener check.
+ */
+ protected static void runNotificationListenerCheck() throws Throwable {
+ TestUtils.awaitJobUntilRequestedState(
+ PERMISSION_CONTROLLER_PKG,
+ NOTIFICATION_LISTENER_CHECK_JOB_ID,
+ UNEXPECTED_TIMEOUT_MILLIS,
+ sUiAutomation,
+ "waiting"
+ );
+
+ TestUtils.runJobAndWaitUntilCompleted(
+ PERMISSION_CONTROLLER_PKG,
+ NOTIFICATION_LISTENER_CHECK_JOB_ID,
+ UNEXPECTED_TIMEOUT_MILLIS,
+ sUiAutomation
+ );
+ }
+
+ /**
+ * Skip tests for if Safety Center not supported
+ */
+ protected void assumeDeviceSupportsSafetyCenter() {
+ assumeTrue(SafetyCenterUtils.deviceSupportsSafetyCenter(sContext));
+ }
+
+ /**
+ * Skip tests for if Safety Center IS supported
+ */
+ protected void assumeDeviceDoesNotSupportSafetyCenter() {
+ assumeFalse(SafetyCenterUtils.deviceSupportsSafetyCenter(sContext));
+ }
+
+ protected void wakeUpAndDismissKeyguard() {
+ runShellCommand("input keyevent KEYCODE_WAKEUP");
+ runShellCommand("wm dismiss-keyguard");
+ }
+
+ /**
+ * Reset the permission controllers state before each test
+ */
+ protected void resetPermissionControllerBeforeEachTest() throws Throwable {
+ resetPermissionController();
+
+ // ensure no posted notification listener notifications exits
+ eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ // Reset job scheduler stats (to allow more jobs to be run)
+ runShellCommand(
+ "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " "
+ + PERMISSION_CONTROLLER_PKG);
+ runShellCommand("cmd jobscheduler reset-schedule-quota");
+ }
+
+ /**
+ * Reset the permission controllers state.
+ */
+ private static void resetPermissionController() throws Throwable {
+ PermissionUtils.resetPermissionControllerJob(sUiAutomation, PERMISSION_CONTROLLER_PKG,
+ NOTIFICATION_LISTENER_CHECK_JOB_ID, 45000,
+ ACTION_SET_UP_NOTIFICATION_LISTENER_CHECK, NotificationListenerOnBootReceiver);
+ }
+
+ /**
+ * Preshow/dismiss cts NotificationListener notification as it negatively affects test results
+ * (can result in unexpected test pass/failures)
+ */
+ protected void triggerAndDismissCtsNotificationListenerNotification() throws Throwable {
+ // CtsNotificationListenerService isn't enabled at this point, but NotificationListener
+ // should be. Mark as notified by showing and dismissing
+ runNotificationListenerCheck();
+
+ // Ensure notification shows and dismiss
+ eventually(() -> assertNotNull(getNotification(true)),
+ UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ /**
+ * Get a notification listener notification that is currently visible.
+ *
+ * @param cancelNotification if `true` the notification is canceled inside this method
+ * @return The notification or `null` if there is none
+ */
+ protected StatusBarNotification getNotification(boolean cancelNotification) throws Throwable {
+ return CtsNotificationListenerServiceUtils.getNotificationForPackageAndId(
+ PERMISSION_CONTROLLER_PKG,
+ NOTIFICATION_LISTENER_CHECK_NOTIFICATION_ID,
+ cancelNotification);
+ }
+
+ /**
+ * Clear any notifications related to NotificationListenerCheck to ensure clean test setup
+ */
+ protected void clearNotifications() throws Throwable {
+ // Clear notification if present
+ CtsNotificationListenerServiceUtils.cancelNotifications(PERMISSION_CONTROLLER_PKG);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/Camera2PermissionTest.java b/tests/cts/permission/src/android/permission/cts/Camera2PermissionTest.java
new file mode 100644
index 000000000..379f47815
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/Camera2PermissionTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2014 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.permission.cts;
+
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.content.Context;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.platform.test.annotations.Presubmit;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for Camera2 API related Permissions. Currently, this means
+ * android.permission.CAMERA.
+ */
+public class Camera2PermissionTest extends AndroidTestCase {
+ private static final String TAG = "Camera2PermissionTest";
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private static final int CAMERA_CLOSE_TIMEOUT_MS = 2000;
+
+ private CameraManager mCameraManager;
+ private CameraDevice mCamera;
+ private BlockingStateCallback mCameraListener;
+ private String[] mCameraIds;
+ protected Handler mHandler;
+ protected HandlerThread mHandlerThread;
+
+ @Override
+ public void setContext(Context context) {
+ super.setContext(context);
+ mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+ assertNotNull("Can't connect to camera manager!", mCameraManager);
+ }
+
+ /**
+ * Set up the camera2 test case required environments, including CameraManager,
+ * HandlerThread, Camera IDs, and CameraStateCallback etc.
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mCameraIds = mCameraManager.getCameraIdList();
+ assertNotNull("Camera ids shouldn't be null", mCameraIds);
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ mCameraListener = new BlockingStateCallback();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mHandlerThread.quitSafely();
+ mHandler = null;
+
+ super.tearDown();
+ }
+
+ /**
+ * Attempt to open camera. Requires Permission:
+ * {@link android.Manifest.permission#CAMERA}.
+ */
+ public void testCameraOpen() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ openCamera(id);
+ fail("Was able to open camera " + id + " with no permission");
+ }
+ catch (SecurityException e) {
+ // expected
+ } finally {
+ closeCamera();
+ }
+ }
+ }
+
+ /**
+ * Check that no system cameras can be discovered without
+ * {@link android.Manifest.permission#CAMERA} and android.permission.SYSTEM_CAMERA
+ */
+ public void testSystemCameraDiscovery() throws Exception {
+ for (String id : mCameraIds) {
+ Log.i(TAG, "testSystemCameraDiscovery for camera id " + id);
+ CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(id);
+ assertNotNull("Camera characteristics shouldn't be null", characteristics);
+ int[] availableCapabilities =
+ characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ assertTrue("Camera capabilities shouldn't be null", availableCapabilities != null);
+ List<Integer> capList = toList(availableCapabilities);
+ assertFalse("System camera device " + id + " should not be public",
+ capList.contains(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA));
+ }
+ }
+
+ /**
+ * Check the absence of camera characteristics keys that require Permission:
+ * {@link android.Manifest.permission#CAMERA}.
+ */
+ public void testCameraCharacteristicsNeedingPermission() throws Exception {
+ for (String id : mCameraIds) {
+ CameraCharacteristics capabilities = mCameraManager.getCameraCharacteristics(id);
+ assertNotNull("Camera characteristics shouldn't be null", capabilities);
+ List<Key<?>> keysNeedingPermission = capabilities.getKeysNeedingPermission();
+ if (keysNeedingPermission == null) {
+ continue;
+ }
+ List<Key<?>> keys = capabilities.getKeys();
+ assertNotNull("Camera characteristics key list shouldn't be null", keys);
+ for (Key<?> key : keysNeedingPermission) {
+ assertEquals("Key " + key.getName() + " needing permission is part of the" +
+ " available characteristics keys", -1, keys.indexOf(key));
+ assertNull("Key " + key.getName() + " needing permission must not present" +
+ " in camera characteristics", capabilities.get(key));
+ }
+ }
+ }
+
+ /**
+ * Add and remove availability listeners should work without permission.
+ */
+ @Presubmit
+ public void testAvailabilityCallback() throws Exception {
+ DummyCameraListener availabilityListener = new DummyCameraListener();
+ // Remove a not-registered listener is a no-op.
+ mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+ mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+ mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+ mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+ mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+ mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+ // Remove a previously-added listener second time is a no-op.
+ mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+ }
+
+ private class DummyCameraListener extends CameraManager.AvailabilityCallback {
+ @Override
+ public void onCameraAvailable(String cameraId) {
+ }
+
+ @Override
+ public void onCameraUnavailable(String cameraId) {
+ }
+ }
+
+ private void openCamera(String cameraId) throws Exception {
+ mCamera = (new BlockingCameraManager(mCameraManager)).openCamera(
+ cameraId, mCameraListener, mHandler);
+ }
+
+ private static List<Integer> toList(int[] array) {
+ List<Integer> list = new ArrayList<Integer>();
+ for (int i : array) {
+ list.add(i);
+ }
+ return list;
+ }
+
+ private void closeCamera() {
+ if (mCamera != null) {
+ mCamera.close();
+ mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+ mCamera = null;
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java b/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java
new file mode 100644
index 000000000..99f2862f1
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/CameraPermissionTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.hardware.Camera;
+import android.os.Environment;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.io.FileOutputStream;
+
+/**
+ * Tests for camera-related Permissions. Currently, this means
+ * android.permission.CAMERA.
+ */
+public class CameraPermissionTest extends AndroidTestCase {
+
+ private static String PATH_PREFIX = Environment.getExternalStorageDirectory().toString();
+ private static String CAMERA_IMAGE_PATH = PATH_PREFIX + "this-should-not-exist.jpg";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ class ShutterCallback implements Camera.ShutterCallback {
+ public void onShutter() { }
+ }
+
+ class RawPictureCallback implements Camera.PictureCallback {
+ public void onPictureTaken(byte [] rawData, Camera camera) { }
+ }
+
+ class JpegPictureCallback implements Camera.PictureCallback {
+ public void onPictureTaken(byte [] jpegData, Camera camera) {
+ if (jpegData == null) {
+ // TODO: Is this good (= expected, = correct), or weird, or bad?
+ return;
+ }
+
+ try {
+ FileOutputStream s = new FileOutputStream(CAMERA_IMAGE_PATH);
+ s.write(jpegData);
+ s.flush();
+ }
+ catch (SecurityException e) {
+ // Sure, NOW they tell us (NOTE: this could be a side effect
+ // of the upcoming WRITE_EXTERNAL_STORAGE permission).
+ } catch (Exception e) {
+ // We didn't really need to save it anyway, did we?
+ }
+
+ fail("Successfully captured an image of " + jpegData.length +
+ " bytes, and saved it to " + CAMERA_IMAGE_PATH);
+ }
+ }
+
+ /**
+ * Attempt to take a picture. Requires Permission:
+ * {@link android.Manifest.permission#CAMERA}.
+ */
+ @MediumTest
+ public void testCamera() {
+ try {
+ (Camera.open()).takePicture(new ShutterCallback(),
+ new RawPictureCallback(),
+ new JpegPictureCallback());
+ fail("Was able to take a picture with the camera with no permission");
+ }
+ catch (SecurityException e) {
+ // expected
+ } catch (RuntimeException e) {
+ // expected
+ // The JNI layer isn't translating the EPERM error status into
+ // a SecurityException.
+ }
+ }
+
+}
+
diff --git a/tests/cts/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java b/tests/cts/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java
new file mode 100644
index 000000000..0e8797d20
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.OemNetworkPreferences;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+* Test that protected android.net.ConnectivityManager methods cannot be called without
+* permissions
+*/
+@RunWith(AndroidJUnit4.class)
+public class ConnectivityManagerPermissionTest {
+
+ private ConnectivityManager mConnectivityManager;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ assertNotNull(mConnectivityManager);
+ }
+
+ /**
+ * Verify that calling {@link ConnectivityManager#getNetworkInfo(int))}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ */
+ @Test
+ public void testGetNetworkInfo() {
+ try {
+ mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
+ fail("Was able to call getNetworkInfo");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that calling {@link ConnectivityManager#setOemNetworkPreference(OemNetworkPreferences,
+ * Executor, ConnectivityManager.OnSetOemNetworkPreferenceListener)}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#CONTROL_OEM_PAID_NETWORK_PREFERENCE}.
+ */
+ @Test
+ public void testSetOemNetworkPreference() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ try {
+ final String testPackage = "does.not.matter.com";
+ final int testPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+ final OemNetworkPreferences preferences =
+ new OemNetworkPreferences.Builder()
+ .addNetworkPreference(testPackage, testPref)
+ .build();
+ mConnectivityManager.setOemNetworkPreference(preferences, null, null);
+ fail("Was able to call setOemNetworkPreference");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that calling {@link ConnectivityManager#setOemNetworkPreference(OemNetworkPreferences,
+ * Executor, ConnectivityManager.OnSetOemNetworkPreferenceListener)}
+ * requires automotive feature.
+ * <p>Tests Feature:
+ * {@link PackageManager#FEATURE_AUTOMOTIVE}.
+ */
+ @Test
+ public void testSetOemNetworkPreferenceHasAutomotiveFeature() {
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ try {
+ final String testPackage = "does.not.matter.com";
+ final int testPref = OemNetworkPreferences.OEM_NETWORK_PREFERENCE_OEM_PAID;
+ final OemNetworkPreferences preferences =
+ new OemNetworkPreferences.Builder()
+ .addNetworkPreference(testPackage, testPref)
+ .build();
+ mConnectivityManager.setOemNetworkPreference(preferences, null, null);
+ fail("Was able to call setOemNetworkPreference");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java b/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java
new file mode 100644
index 000000000..984fd6cfe
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ContactsProviderTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2013 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.permission.cts;
+
+import android.content.ContentValues;
+import android.provider.ContactsContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify permissions are enforced.
+ */
+public class ContactsProviderTest extends AndroidTestCase {
+
+ /**
+ * Verifies that query(ContactsContract.Contacts.CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#READ_CONTACTS}.
+ */
+ @SmallTest
+ public void testQueryContacts() {
+ try {
+ getContext().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
+ null, null, null, null);
+ fail("query(ContactsContract.Contacts.CONTENT_URI) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that insert(ContactsContract.Contacts.CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#WRITE_CONTACTS}.
+ */
+ @SmallTest
+ public void testInsertContacts() {
+ try {
+ getContext().getContentResolver().insert(ContactsContract.Contacts.CONTENT_URI,
+ new ContentValues());
+ fail("insert(ContactsContract.Contacts.CONTENT_URI) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that query(ContactsContract.Profile.CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#READ_CONTACTS}.
+ */
+ @SmallTest
+ public void testQueryProfile() {
+ try {
+ getContext().getContentResolver().query(ContactsContract.Profile.CONTENT_URI,
+ null, null, null, null);
+ fail("query(ContactsContract.Profile.CONTENT_URI) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that insert(ContactsContract.Profile.CONTENT_URI) requires
+ * Permission. The provider doesn't actually let you do this even if you have the
+ * permission, but trying to do it without the permission should throw a
+ * SecurityException anyway.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#WRITE_CONTACTS}.
+ */
+ @SmallTest
+ public void testInsertProfile() {
+ try {
+ getContext().getContentResolver().insert(ContactsContract.Profile.CONTENT_URI,
+ new ContentValues(0));
+ fail("insert(ContactsContract.Profile.CONTENT_URI) did not throw SecurityException "
+ + "as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that update(ContactsContract.Profile.CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#WRITE_CONTACTS}.
+ */
+ @SmallTest
+ public void testUpdateProfile() {
+ try {
+ getContext().getContentResolver().update(ContactsContract.Profile.CONTENT_URI,
+ new ContentValues(0), null, null);
+ fail("update(ContactsContract.Profile.CONTENT_URI) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that query(ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
+ */
+ @SmallTest
+ public void testQueryPhoneEnterprise() {
+ try {
+ getContext().getContentResolver().query(
+ ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI,
+ null, null, null, null);
+ fail("query(ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI) did not"
+ + " throw SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that query(ContactsContract.RawContactsEntity.CORP_CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
+ */
+ @SmallTest
+ public void testRawContactsEntityCorp() {
+ try {
+ getContext().getContentResolver().query(
+ ContactsContract.RawContactsEntity.CORP_CONTENT_URI, null, null, null, null);
+ fail("query(ContactsContract.RawContactsEntity.CORP_CONTENT_URI) did not throw"
+ + " SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/DebuggableTest.java b/tests/cts/permission/src/android/permission/cts/DebuggableTest.java
new file mode 100644
index 000000000..7ca734887
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/DebuggableTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 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.permission.cts;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Verify that pre-installed packages don't have the debuggable
+ * flag set. The debuggable flag allows should only be used during
+ * development, and never for shipping devices.
+ */
+public class DebuggableTest extends AndroidTestCase {
+
+ public void testNoDebuggable() {
+ Set<String> debuggableApps = new HashSet<String>();
+ List<ApplicationInfo> apps = getContext()
+ .getPackageManager()
+ .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
+ for (ApplicationInfo app : apps) {
+ if (!app.isSystemApp()) {
+ continue;
+ }
+ String appName = app.packageName;
+ if ((app.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE) {
+ debuggableApps.add(appName);
+ }
+ }
+ assertTrue("Packages marked debuggable: " + debuggableApps, debuggableApps.isEmpty());
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt
new file mode 100644
index 000000000..8bacb46d9
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2023 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.permission.cts
+
+import android.Manifest
+import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
+import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE
+import android.app.Instrumentation
+import android.companion.virtual.VirtualDeviceManager
+import android.companion.virtual.VirtualDeviceManager.VirtualDevice
+import android.companion.virtual.VirtualDeviceParams
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME
+import android.content.pm.PackageManager.PERMISSION_DENIED
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import android.os.Build
+import android.os.UserHandle
+import android.permission.PermissionManager
+import android.platform.test.annotations.AppModeFull
+import android.virtualdevice.cts.common.FakeAssociationRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.AdoptShellPermissionsRule
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assume.assumeNotNull
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@AppModeFull(reason = " cannot be accessed by instant apps")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
+class DevicePermissionsTest {
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val defaultDeviceContext = instrumentation.targetContext
+
+ private lateinit var virtualDevice: VirtualDevice
+ private lateinit var virtualDeviceContext: Context
+
+ private lateinit var permissionManager: PermissionManager
+
+ @get:Rule var mFakeAssociationRule = FakeAssociationRule()
+
+ @get:Rule
+ val mAdoptShellPermissionsRule =
+ AdoptShellPermissionsRule(
+ instrumentation.uiAutomation,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE,
+ Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+ )
+
+ @Before
+ fun setup() {
+ val virtualDeviceManager =
+ defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)
+ assumeNotNull(virtualDeviceManager)
+ virtualDevice =
+ virtualDeviceManager!!.createVirtualDevice(
+ mFakeAssociationRule.getAssociationInfo().getId(),
+ VirtualDeviceParams.Builder().build()
+ )
+ virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId)
+ permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!!
+ runShellCommandOrThrow("pm install -r $TEST_APK")
+ }
+
+ @After
+ fun cleanup() {
+ runShellCommandOrThrow("pm uninstall $TEST_PACKAGE_NAME")
+ virtualDevice.close()
+ }
+
+ @Test
+ fun testDeviceAwareRuntimePermissionIsGranted() {
+ grantPermissionAndAssertGranted(Manifest.permission.CAMERA, virtualDeviceContext)
+ }
+
+ @Test
+ fun testDeviceAwareRuntimePermissionGrantIsInherited() {
+ grantPermissionAndAssertGranted(Manifest.permission.CAMERA, defaultDeviceContext)
+
+ assertPermission(
+ Manifest.permission.CAMERA, PERMISSION_GRANTED, virtualDeviceContext
+ )
+ }
+
+ @Test
+ fun testNonDeviceAwareRuntimePermissionGrantIsInherited() {
+ grantPermissionAndAssertGranted(Manifest.permission.READ_CONTACTS, defaultDeviceContext)
+
+ assertPermission(
+ Manifest.permission.READ_CONTACTS, PERMISSION_GRANTED, virtualDeviceContext
+ )
+ }
+
+ @Test
+ fun testDeviceAwareRuntimePermissionIsRevoked() {
+ grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+
+ revokePermissionAndAssertDenied(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ }
+
+ @Test
+ fun testNonDeviceAwareRuntimePermissionIsRevokedForDefaultDevice() {
+ grantPermissionAndAssertGranted(Manifest.permission.READ_CONTACTS, defaultDeviceContext)
+ assertPermission(
+ Manifest.permission.READ_CONTACTS, PERMISSION_GRANTED, virtualDeviceContext
+ )
+ // Revoke call from virtualDeviceContext should revoke for default device as well.
+ revokePermissionAndAssertDenied(Manifest.permission.READ_CONTACTS, virtualDeviceContext)
+ assertPermission(Manifest.permission.READ_CONTACTS, PERMISSION_DENIED, defaultDeviceContext)
+ }
+
+ @Test
+ fun testNormalPermissionGrantIsInherited() {
+ assertPermission(Manifest.permission.INTERNET, PERMISSION_GRANTED, virtualDeviceContext)
+ }
+
+ @Test
+ fun testSignaturePermissionGrantIsInherited() {
+ assertPermission(CUSTOM_SIGNATURE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext)
+ }
+
+ @Test
+ fun testOneTimePermissionIsRevoked() {
+ grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ virtualDeviceContext.packageManager.updatePermissionFlags(
+ Manifest.permission.RECORD_AUDIO, TEST_PACKAGE_NAME, FLAG_PERMISSION_ONE_TIME,
+ FLAG_PERMISSION_ONE_TIME, UserHandle.of(virtualDeviceContext.userId)
+ )
+
+ permissionManager.startOneTimePermissionSession(
+ TEST_PACKAGE_NAME, 0, 0, IMPORTANCE_FOREGROUND, IMPORTANCE_FOREGROUND_SERVICE)
+ eventually {
+ assertPermission(
+ Manifest.permission.RECORD_AUDIO, PERMISSION_DENIED, virtualDeviceContext
+ )
+ }
+ }
+
+ @Test
+ fun testRevokeSelfPermissionOnKill() {
+ grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+
+ revokeSelfPermission(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ eventually {
+ assertPermission(
+ Manifest.permission.RECORD_AUDIO, PERMISSION_DENIED, virtualDeviceContext
+ )
+ }
+ }
+
+ private fun revokeSelfPermission(permissionName: String, context: Context) {
+ val intent = Intent(PERMISSION_SELF_REVOKE_INTENT)
+ intent.setClassName(TEST_PACKAGE_NAME, PERMISSION_SELF_REVOKE_RECEIVER)
+ intent.putExtra("permissionName", permissionName)
+ intent.putExtra("deviceID", context.deviceId)
+ context.sendBroadcast(intent)
+ waitForBroadcasts()
+ }
+
+ private fun grantPermissionAndAssertGranted(permissionName: String, context: Context) {
+ context.packageManager.grantRuntimePermission(
+ TEST_PACKAGE_NAME, permissionName, UserHandle.of(context.userId)
+ )
+ assertPermission(permissionName, PERMISSION_GRANTED, context)
+ }
+
+ private fun revokePermissionAndAssertDenied(permissionName: String, context: Context) {
+ context.packageManager.revokeRuntimePermission(
+ TEST_PACKAGE_NAME, permissionName, UserHandle.of(context.userId)
+ )
+ assertPermission(permissionName, PERMISSION_DENIED, context)
+ }
+
+ private fun assertPermission(
+ permissionName: String,
+ permissionState: Int,
+ context: Context,
+ ) {
+ assertThat(context.packageManager.checkPermission(permissionName, TEST_PACKAGE_NAME))
+ .isEqualTo(permissionState)
+ }
+
+ companion object {
+ private const val TEST_PACKAGE_NAME = "android.permission.cts.appthatrequestpermission"
+ private const val TEST_APK =
+ "/data/local/tmp/cts-permission/CtsAppThatRequestsDevicePermissions.apk"
+
+ private const val CUSTOM_SIGNATURE_PERMISSION =
+ "android.permission.cts.CUSTOM_SIGNATURE_PERMISSION"
+
+ private const val PERMISSION_SELF_REVOKE_INTENT =
+ "android.permission.cts.appthatrequestpermission.REVOKE_SELF_PERMISSION"
+ private const val PERMISSION_SELF_REVOKE_RECEIVER =
+ "android.permission.cts.appthatrequestpermission.RevokeSelfPermissionReceiver"
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt b/tests/cts/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt
new file mode 100644
index 000000000..14454957a
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/DuplicatePermissionDefinitionsTest.kt
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2020 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.permission.cts
+
+import android.content.pm.PackageManager
+import android.content.pm.PermissionGroupInfo
+import android.content.pm.PermissionInfo
+import android.os.Build
+import android.platform.test.annotations.AppModeFull
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SdkSuppress
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
+import com.android.compatibility.common.util.ShellUtils.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val APK_PATH = "/data/local/tmp/cts-permission/"
+
+private const val APK_DEFINING_PERM_A = "${APK_PATH}CtsAppThatDefinesPermissionA.apk"
+private const val APK_ALSO_DEFINING_PERM_A = "${APK_PATH}CtsAppThatAlsoDefinesPermissionA.apk"
+private const val APK_ALSO_DEFINING_PERM_A_DIFFERENT_CERT =
+ "${APK_PATH}CtsAppThatAlsoDefinesPermissionADifferentCert.apk"
+private const val APK_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT =
+ "${APK_PATH}CtsAppThatAlsoDefinesPermissionGroupADifferentCert.apk"
+private const val APK_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT_SDK_30 =
+ "${APK_PATH}CtsAppThatAlsoDefinesPermissionGroupADifferentCert30.apk"
+private const val APK_DEFINING_PERM_WITH_INVALID_GROUP =
+ "${APK_PATH}CtsAppThatDefinesPermissionWithInvalidGroup.apk"
+private const val APK_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30 =
+ "${APK_PATH}CtsAppThatDefinesPermissionWithInvalidGroup30.apk"
+private const val APK_DEFINING_PERM_IN_PLATFORM_GROUP =
+ "${APK_PATH}CtsAppThatDefinesPermissionInPlatformGroup.apk"
+
+private const val APP_DEFINING_PERM_A = "android.permission.cts.appthatdefinespermissiona"
+private const val APP_ALSO_DEFINING_PERM_A = "android.permission.cts.appthatalsodefinespermissiona"
+private const val APP_ALSO_DEFINING_PERM_A_DIFFERENT_CERT =
+ "android.permission.cts.appthatdefinespermissiona.differentcert"
+private const val APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT =
+ "android.permission.cts.appthatdefinespermissiongroupa.differentcert"
+private const val APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT_SDK_30 =
+ "android.permission.cts.appthatdefinespermissiongroupa.differentcert30"
+private const val APP_DEFINING_PERM_IN_PLATFORM_GROUP =
+ "android.permission.cts.appthatdefinespermissioninplatformgroup"
+private const val APP_DEFINING_PERM_WITH_INVALID_GROUP =
+ "android.permission.cts.appthatdefinespermissionwithinvalidgroup"
+private const val APP_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30 =
+ "android.permission.cts.appthatdefinespermissionwithinvalidgroup30"
+
+private const val PERM_A = "com.android.cts.duplicatepermission.permA"
+private const val GROUP_A = "com.android.cts.duplicatepermission.groupA"
+private const val INVALID_GROUP = "com.android.cts.duplicatepermission.invalid"
+
+/**
+ * Test cases where packages
+ * - define the same permission or
+ * - define the same permission group
+ * - define permissions in a group defined by another package
+ */
+@AppModeFull(reason = "Tests properties of other app. Instant apps cannot interact with other apps")
+@RunWith(AndroidJUnit4ClassRunner::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+class DuplicatePermissionDefinitionsTest {
+ private val pm = InstrumentationRegistry.getTargetContext().packageManager
+
+ private fun install(apk: String) {
+ runShellCommandOrThrow("pm install $apk")
+ }
+
+ private fun uninstall(app: String) {
+ runShellCommand("pm uninstall $app")
+ }
+
+ private val allPackages: List<String>
+ get() = pm.getInstalledPackages(0).map { it.packageName }
+
+ private val permAInfo: PermissionInfo
+ get() = pm.getPermissionInfo(PERM_A, 0)!!
+
+ private val groupAInfo: PermissionGroupInfo
+ get() = pm.getPermissionGroupInfo(GROUP_A, 0)!!
+
+ @Test
+ fun canInstallAppsDefiningSamePermissionWhenSameCert() {
+ install(APK_DEFINING_PERM_A)
+ install(APK_ALSO_DEFINING_PERM_A)
+
+ assertThat(allPackages).containsAtLeast(APP_DEFINING_PERM_A, APP_ALSO_DEFINING_PERM_A)
+
+ assertThat(permAInfo.packageName).isEqualTo(APP_DEFINING_PERM_A)
+ }
+
+ @Test
+ fun cannotInstallAppsDefiningSamePermissionWhenDifferentCert() {
+ install(APK_DEFINING_PERM_A)
+ install(APK_ALSO_DEFINING_PERM_A_DIFFERENT_CERT)
+
+ assertThat(allPackages).contains(APP_DEFINING_PERM_A)
+ assertThat(allPackages).doesNotContain(APP_ALSO_DEFINING_PERM_A_DIFFERENT_CERT)
+
+ assertThat(permAInfo.packageName).isEqualTo(APP_DEFINING_PERM_A)
+ }
+
+ @Test
+ fun canInstallAppsDefiningSamePermissionGroupWhenDifferentCertIfSdk30() {
+ install(APK_DEFINING_PERM_A)
+ install(APK_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT_SDK_30)
+
+ assertThat(allPackages).containsAtLeast(APP_DEFINING_PERM_A,
+ APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT_SDK_30)
+
+ assertThat(groupAInfo.packageName).isEqualTo(APP_DEFINING_PERM_A)
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = [146211400])
+ fun cannotInstallAppsDefiningSamePermissionGroupWhenDifferentCert() {
+ install(APK_DEFINING_PERM_A)
+ install(APK_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT)
+
+ assertThat(allPackages).contains(APP_DEFINING_PERM_A)
+ assertThat(allPackages).doesNotContain(APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT)
+
+ assertThat(groupAInfo.packageName).isEqualTo(APP_DEFINING_PERM_A)
+ }
+
+ // This is the same as cannotInstallAppsDefiningSamePermissionGroupWhenDifferentCert but this
+ // case is allowed as the package that originally defined the group is a platform.
+ @Test
+ fun canInstallAppsDefiningPermissionInPlatformGroup() {
+ install(APK_DEFINING_PERM_IN_PLATFORM_GROUP)
+
+ assertThat(allPackages).contains(APP_DEFINING_PERM_IN_PLATFORM_GROUP)
+
+ assertThat(permAInfo.packageName).isEqualTo(APP_DEFINING_PERM_IN_PLATFORM_GROUP)
+ assertThat(permAInfo.group).isEqualTo(android.Manifest.permission_group.CAMERA)
+ assertThat(pm.getPermissionGroupInfo(android.Manifest.permission_group.CAMERA, 0)!!
+ .packageName).isEqualTo("android")
+ }
+
+ @Test
+ fun canInstallAppsDefiningPermissionWithInvalidGroupSdk30() {
+ install(APK_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30)
+
+ assertThat(allPackages).contains(APP_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30)
+
+ assertThat(permAInfo.packageName).isEqualTo(APP_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30)
+ assertThat(permAInfo.group).isEqualTo(INVALID_GROUP)
+ }
+
+ @Test(expected = PackageManager.NameNotFoundException::class)
+ @AsbSecurityTest(cveBugId = [146211400])
+ fun cannotInstallAppsDefiningPermissionWithInvalidGroup() {
+ install(APK_DEFINING_PERM_WITH_INVALID_GROUP)
+
+ assertThat(allPackages).doesNotContain(APP_DEFINING_PERM_WITH_INVALID_GROUP)
+
+ // throws a NameNotFoundException as perm info does not exist
+ permAInfo
+ }
+
+ @After
+ fun uninstallTestApps() {
+ uninstall(APP_DEFINING_PERM_A)
+ uninstall(APP_ALSO_DEFINING_PERM_A)
+ uninstall(APP_ALSO_DEFINING_PERM_A_DIFFERENT_CERT)
+ uninstall(APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT)
+ uninstall(APP_ALSO_DEFINING_PERM_GROUP_A_DIFFERENT_CERT_SDK_30)
+ uninstall(APP_DEFINING_PERM_IN_PLATFORM_GROUP)
+ uninstall(APP_DEFINING_PERM_WITH_INVALID_GROUP)
+ uninstall(APP_DEFINING_PERM_WITH_INVALID_GROUP_SDK_30)
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/EthernetManagerPermissionTest.java b/tests/cts/permission/src/android/permission/cts/EthernetManagerPermissionTest.java
new file mode 100644
index 000000000..3c99b34a9
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/EthernetManagerPermissionTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.permission.cts;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.EthernetManager;
+import android.net.EthernetNetworkUpdateRequest;
+import android.net.IpConfiguration;
+import android.net.NetworkCapabilities;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+
+/**
+ * Test protected android.net.EthernetManager methods cannot be called without permissions.
+ */
+@RunWith(AndroidJUnit4.class)
+public class EthernetManagerPermissionTest {
+ private static final String TEST_IFACE = "test123abc789";
+ private EthernetManager mEthernetManager;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mEthernetManager = mContext.getSystemService(EthernetManager.class);
+ // mEthernetManager may be null depending on the device's configuration.
+ assumeNotNull(mEthernetManager);
+ }
+
+ private EthernetNetworkUpdateRequest buildUpdateRequest() {
+ return new EthernetNetworkUpdateRequest.Builder()
+ .setIpConfiguration(new IpConfiguration.Builder().build())
+ .setNetworkCapabilities(new NetworkCapabilities.Builder().build())
+ .build();
+ }
+
+ private EthernetNetworkUpdateRequest buildUpdateRequestWithoutCapabilities() {
+ return new EthernetNetworkUpdateRequest.Builder()
+ .setIpConfiguration(new IpConfiguration.Builder().build())
+ .build();
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#updateConfiguration(String,
+ * EthernetNetworkUpdateRequest, Executor, BiConsumer)} requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testUpdateConfigurationRequiresPermissionManageEthernetNetworks() {
+ assertThrows("Should not be able to call updateConfiguration without permission",
+ SecurityException.class,
+ () -> mEthernetManager.updateConfiguration(TEST_IFACE,
+ buildUpdateRequestWithoutCapabilities(), null, null));
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#enableInterface}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testEnableInterface() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call enableInterface without permission",
+ SecurityException.class,
+ () -> mEthernetManager.enableInterface(TEST_IFACE, null, null));
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#disableInterface}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testDisableInterface() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call disableInterface without permission",
+ SecurityException.class,
+ () -> mEthernetManager.disableInterface(TEST_IFACE, null, null));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/cts/permission/src/android/permission/cts/FileSystemPermissionTest.java
new file mode 100644
index 000000000..94557464f
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (C) 2010 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.permission.cts;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStatVfs;
+import android.util.Pair;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.PropertyUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Verify certain permissions on the filesystem
+ *
+ * TODO: Combine this file with {@link android.os.cts.FileAccessPermissionTest}
+ */
+@RunWith(AndroidJUnit4.class)
+public class FileSystemPermissionTest {
+
+ private int dumpable;
+
+ @Before
+ public void setUp() throws Exception {
+ dumpable = Os.prctl(OsConstants.PR_GET_DUMPABLE, 0, 0, 0, 0);
+ Os.prctl(OsConstants.PR_SET_DUMPABLE, 1, 0, 0, 0);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ Os.prctl(OsConstants.PR_SET_DUMPABLE, dumpable, 0, 0, 0);
+ }
+
+ @MediumTest
+ @Test
+ public void testCreateFileHasSanePermissions() throws Exception {
+ File myFile = new File(getContext().getFilesDir(), "hello");
+ FileOutputStream stream = new FileOutputStream(myFile);
+ stream.write("hello world".getBytes());
+ stream.close();
+ try {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ FileUtils.getFileStatus(myFile.getAbsolutePath(), status, false);
+ int expectedPerms = FileUtils.S_IFREG
+ | FileUtils.S_IWUSR
+ | FileUtils.S_IRUSR;
+ assertEquals(
+ "Newly created files should have 0600 permissions",
+ Integer.toOctalString(expectedPerms),
+ Integer.toOctalString(status.mode));
+ } finally {
+ assertTrue(myFile.delete());
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testCreateDirectoryHasSanePermissions() throws Exception {
+ File myDir = new File(getContext().getFilesDir(), "helloDirectory");
+ assertTrue(myDir.mkdir());
+ try {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ FileUtils.getFileStatus(myDir.getAbsolutePath(), status, false);
+ int expectedPerms = FileUtils.S_IFDIR
+ | FileUtils.S_IWUSR
+ | FileUtils.S_IRUSR
+ | FileUtils.S_IXUSR;
+ assertEquals(
+ "Newly created directories should have 0700 permissions",
+ Integer.toOctalString(expectedPerms),
+ Integer.toOctalString(status.mode));
+
+ } finally {
+ assertTrue(myDir.delete());
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testOtherApplicationDirectoriesAreNotWritable() throws Exception {
+ Set<File> writableDirs = new HashSet<File>();
+ List<ApplicationInfo> apps = getContext()
+ .getPackageManager()
+ .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
+ String myAppDirectory = getContext().getApplicationInfo().dataDir;
+ for (ApplicationInfo app : apps) {
+ if (app.dataDir != null && !myAppDirectory.equals(app.dataDir)) {
+ writableDirs.addAll(getWritableDirectoriesAndSubdirectoriesOf(new File(app.dataDir)));
+ }
+ }
+
+ assertTrue("Found writable directories: " + writableDirs.toString(),
+ writableDirs.isEmpty());
+ }
+
+ @MediumTest
+ @Test
+ public void testApplicationParentDirectoryNotWritable() throws Exception {
+ String myDataDir = getContext().getApplicationInfo().dataDir;
+ File parentDir = new File(myDataDir).getParentFile();
+ assertFalse(parentDir.toString(), isDirectoryWritable(parentDir));
+ }
+
+ @MediumTest
+ @Test
+ public void testDataDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(Environment.getDataDirectory()));
+ }
+
+ @MediumTest
+ @Test
+ public void testAndroidRootDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(Environment.getRootDirectory()));
+ }
+
+ @MediumTest
+ @Test
+ public void testDownloadCacheDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(Environment.getDownloadCacheDirectory()));
+ }
+
+ @MediumTest
+ @Test
+ public void testRootDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(new File("/")));
+ }
+
+ @MediumTest
+ @Test
+ public void testDevDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(new File("/dev")));
+ }
+
+ @MediumTest
+ @Test
+ public void testProcDirectoryNotWritable() throws Exception {
+ assertFalse(isDirectoryWritable(new File("/proc")));
+ }
+
+ @MediumTest
+ @Test
+ public void testDevDiagSane() throws Exception {
+ File f = new File("/dev/diag");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ /* b/26813932 */
+ @MediumTest
+ @Test
+ public void testProcInterruptsNotReadable() throws Exception {
+ File f = new File("/proc/interrupts");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ /* b/26813932 */
+ @MediumTest
+ @Test
+ public void testProcStatNotReadable() throws Exception {
+ File f = new File("/proc/stat");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ @MediumTest
+ @Test
+ public void testDevMemSane() throws Exception {
+ File f = new File("/dev/mem");
+ assertFalse(f.exists());
+ }
+
+ @MediumTest
+ @Test
+ public void testDevkmemSane() throws Exception {
+ File f = new File("/dev/kmem");
+ assertFalse(f.exists());
+ }
+
+ @MediumTest
+ @Test
+ public void testDevPortSane() throws Exception {
+ File f = new File("/dev/port");
+ assertFalse(f.exists());
+ }
+
+ @MediumTest
+ @Test
+ public void testPn544Sane() throws Exception {
+ File f = new File("/dev/pn544");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "nfc");
+ assertFileOwnedByGroup(f, "nfc");
+ }
+
+ @MediumTest
+ @Test
+ public void testBcm2079xSane() throws Exception {
+ File f = new File("/dev/bcm2079x");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "nfc");
+ assertFileOwnedByGroup(f, "nfc");
+ }
+
+ @MediumTest
+ @Test
+ public void testBcm2079xi2cSane() throws Exception {
+ File f = new File("/dev/bcm2079x-i2c");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "nfc");
+ assertFileOwnedByGroup(f, "nfc");
+ }
+
+ @MediumTest
+ @Test
+ public void testDevQtaguidSane() throws Exception {
+ File f = new File("/dev/xt_qtaguid");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "root");
+ }
+
+ @MediumTest
+ @Test
+ public void testProcQtaguidCtrlSane() throws Exception {
+ File f = new File("/proc/net/xt_qtaguid/ctrl");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "net_bw_acct");
+ }
+
+ @MediumTest
+ @Test
+ public void testProcQtaguidStatsSane() throws Exception {
+ File f = new File("/proc/net/xt_qtaguid/stats");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "net_bw_stats");
+ }
+
+ private static List<String> procNetFiles = Arrays.asList("anycast6", "arp", "arp_tables_matches",
+ "arp_tables_names", "arp_tables_targets", "dev", "dev_mcast", "fib_trie", "fib_triestat",
+ "hci", "icmp", "icmp6", "if_inet6", "igmp", "igmp6", "ip6_flowlabel",
+ "ip6_tables_matches", "ip6_tables_names", "ip6_tables_targets", "ip_tables_matches",
+ "ip_tables_names", "ip_tables_targets", "ipv6_route", "l2cap", "mcfilter", "mcfilter6",
+ "netlink", "netstat", "nf_conntrack", "nf_conntrack_expect", "packet", "pfkey", "pnp",
+ "pppoe", "pppol2tp", "protocols", "psched", "ptype", "raw", "raw6", "route", "rt6_stats",
+ "rt_cache", "sco", "snmp", "snmp6", "sockstat", "sockstat6", "softnet_stat", "tcp",
+ "tcp6", "udp", "udp6", "udplite", "udplite6", "unix", "wireless", "xfrm_stat");
+
+ private static void procNetSane(String path) {
+ File f = new File(path);
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "root");
+ }
+
+ @MediumTest
+ @Test
+ public void testProcNetSane() throws Exception {
+ if (PropertyUtil.isVendorApiLevelNewerThan(28)) {
+ for (String file : procNetFiles) {
+ procNetSane("/proc/net/" + file);
+ }
+ }
+ }
+
+ private static int readInt(File f) throws FileNotFoundException {
+ try (Scanner s = new Scanner(f)) {
+ return s.nextInt();
+ }
+ }
+
+ private static boolean writeInt(File f, int value) throws IOException {
+ try (FileOutputStream os = new FileOutputStream(f)) {
+ try {
+ os.write(Integer.toString(value).getBytes());
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testProcSelfOomAdjSane() throws IOException {
+ final int OOM_DISABLE = -17;
+
+ File f = new File("/proc/self/oom_adj");
+ assertTrue(f.canRead());
+ assertFalse(f.canExecute());
+
+ int oom_adj = readInt(f);
+ assertNotEquals("unprivileged processes should not be unkillable", OOM_DISABLE, oom_adj);
+ if (f.canWrite())
+ assertFalse("unprivileged processes should not be able to reduce their oom_adj value",
+ writeInt(f, oom_adj - 1));
+ }
+
+ @MediumTest
+ @Test
+ public void testProcSelfOomScoreAdjSane() throws IOException {
+ final int OOM_SCORE_ADJ_MIN = -1000;
+
+ File f = new File("/proc/self/oom_score_adj");
+ assertTrue(f.canRead());
+ assertFalse(f.canExecute());
+
+ int oom_score_adj = readInt(f);
+ assertNotEquals("unprivileged processes should not be unkillable", OOM_SCORE_ADJ_MIN, oom_score_adj);
+ if (f.canWrite()) {
+ assertFalse(
+ "unprivileged processes should not be able to reduce their oom_score_adj value",
+ writeInt(f, oom_score_adj - 1));
+ assertTrue(
+ "unprivileged processes should be able to increase their oom_score_adj value",
+ writeInt(f, oom_score_adj + 1));
+ assertTrue("unprivileged processes should be able to restore their oom_score_adj value",
+ writeInt(f, oom_score_adj));
+ }
+ }
+
+ private static List<Pair<Long, Long>> mappedPageRanges() throws IOException {
+ final BigInteger PAGE_SIZE = new BigInteger("4096");
+
+ final Pattern mapsPattern = Pattern.compile("^(\\p{XDigit}+)-(\\p{XDigit}+)");
+ List<Pair<Long, Long>> ret = new LinkedList<>();
+
+ BufferedReader reader = new BufferedReader(new FileReader("/proc/self/maps"));
+ String line;
+ try {
+ while ((line = reader.readLine()) != null) {
+ Matcher m = mapsPattern.matcher(line);
+ m.find();
+
+ long start = new BigInteger(m.group(1), 16).divide(PAGE_SIZE).longValue();
+ long end = new BigInteger(m.group(2), 16).divide(PAGE_SIZE).longValue();
+
+ ret.add(new Pair<>(start, end));
+ }
+
+ return ret;
+ } finally {
+ reader.close();
+ }
+ }
+
+ private static boolean pfnIsZero(FileDescriptor pagemap, long start, long end) throws ErrnoException, IOException {
+ // Note: reads from /proc/self/pagemap *must* be 64-bit aligned. Use low-level android.system.Os routines to
+ // ensure this.
+ final int SIZEOF_U64 = 8;
+ final long PAGE_PRESENT = 1L << 63;
+ final long PFN_MASK = (1L << 55) - 1;
+
+ for (long page = start; page < end; page++) {
+ long offset = page * SIZEOF_U64;
+ long seek = Os.lseek(pagemap, offset, OsConstants.SEEK_SET);
+ if (offset != seek)
+ throw new IOException("lseek(" + offset + ") returned " + seek);
+
+ byte bytes[] = new byte[SIZEOF_U64];
+ ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder());
+ int read = Os.read(pagemap, buf);
+
+ if (read == 0)
+ // /proc/[pid]/maps may contain entries that are outside the process's VM space,
+ // like the [vectors] page on 32-bit ARM devices. In this case, seek() succeeds but
+ // read() returns 0. The kernel is telling us that there are no more pagemap
+ // entries to read, so we can stop here.
+ break;
+ else if (read != bytes.length)
+ throw new IOException("read(" + bytes.length + ") returned " + read);
+
+ buf.position(0);
+ long entry = buf.getLong();
+ if ((entry & PAGE_PRESENT) == PAGE_PRESENT && (entry & PFN_MASK) != 0)
+ return false;
+ }
+
+ return true;
+ }
+
+ @MediumTest
+ @Test
+ public void testProcSelfPagemapSane() throws ErrnoException, IOException {
+ FileDescriptor pagemap = null;
+ try {
+ pagemap = Os.open("/proc/self/pagemap", OsConstants.O_RDONLY, 0);
+
+ for (Pair<Long, Long> range : mappedPageRanges())
+ if (!pfnIsZero(pagemap, range.first, range.second))
+ fail("Device is missing the following kernel security patch: "
+ + "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=ab676b7d6fbf4b294bf198fb27ade5b0e865c7ce");
+ } catch (ErrnoException e) {
+ if (e.errno == OsConstants.EPERM)
+ // expected before 4.2
+ return;
+
+ throw e;
+ } finally {
+ if (pagemap != null)
+ Os.close(pagemap);
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testTcpDefaultRwndSane() throws Exception {
+ File f = new File("/proc/sys/net/ipv4/tcp_default_init_rwnd");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "root");
+ }
+
+ @MediumTest
+ @Test
+ public void testIdletimerDirectoryExistsAndSane() throws Exception {
+ File dir = new File("/sys/class/xt_idletimer");
+ assertTrue(dir.isDirectory());
+ assertFalse(dir.canWrite());
+ assertTrue(dir.canExecute());
+
+ assertFileOwnedBy(dir, "root");
+ assertFileOwnedByGroup(dir, "root");
+ }
+
+
+ @MediumTest
+ @Test
+ public void testProcfsMmapRndBitsExistsAndSane() throws Exception {
+ String arch = System.getProperty("os.arch");
+ boolean supported = false;
+ boolean supported_64 = false;
+
+ if (arch.equals("aarch64") || arch.equals("x86_64"))
+ supported_64 = true;
+ else if (arch.startsWith("arm") || arch.endsWith("86"))
+ supported = true;
+
+ /* 64-bit OS should support running 32-bit applications */
+ if (supported_64) {
+ File f = new File("/proc/sys/vm/mmap_rnd_compat_bits");
+ assertTrue(f.exists());
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ if (supported_64 || supported) {
+ File f = new File("/proc/sys/vm/mmap_rnd_bits");
+ assertTrue(f.exists());
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+ }
+
+ /**
+ * Assert that a file is owned by a specific owner. This is a noop if the
+ * file does not exist.
+ *
+ * @param file The file to check.
+ * @param expectedOwner The owner of the file.
+ */
+ private static void assertFileOwnedBy(File file, String expectedOwner) {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ String path = file.getAbsolutePath();
+ if (file.exists() && FileUtils.getFileStatus(path, status, true)) {
+ String actualOwner = FileUtils.getUserName(status.uid);
+ if (!expectedOwner.equals(actualOwner)) {
+ String msg = String.format("Wrong owner. Expected '%s', but found '%s' for %s.",
+ expectedOwner, actualOwner, path);
+ fail(msg);
+ }
+ }
+ }
+
+ /**
+ * Assert that a file is owned by a specific group. This is a noop if the
+ * file does not exist.
+ *
+ * @param file The file to check.
+ * @param expectedGroup The owner group of the file.
+ */
+ private static void assertFileOwnedByGroup(File file, String expectedGroup) {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ String path = file.getAbsolutePath();
+ if (file.exists() && FileUtils.getFileStatus(path, status, true)) {
+ String actualGroup = FileUtils.getGroupName(status.gid);
+ if (!expectedGroup.equals(actualGroup)) {
+ String msg = String.format("Wrong group. Expected '%s', but found '%s' for %s.",
+ expectedGroup, actualGroup, path);
+ fail(msg);
+ }
+ }
+ }
+
+ @MediumTest
+ @Test
+ public void testTtyO3Sane() throws Exception {
+ File f = new File("/dev/ttyO3");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ @MediumTest
+ @Test
+ public void testDataMediaSane() throws Exception {
+ final File f = new File("/data/media");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ @MediumTest
+ @Test
+ public void testMntShellSane() throws Exception {
+ final File f = new File("/mnt/shell");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ @MediumTest
+ @Test
+ public void testMntSecureSane() throws Exception {
+ final File f = new File("/mnt/secure");
+ assertFalse(f.canRead());
+ assertFalse(f.canWrite());
+ assertFalse(f.canExecute());
+ }
+
+ private static boolean isDirectoryWritable(File directory) {
+ File toCreate = new File(directory, "hello");
+ try {
+ toCreate.createNewFile();
+ return true;
+ } catch (IOException e) {
+ // It's expected we'll get a "Permission denied" exception.
+ } finally {
+ toCreate.delete();
+ }
+ return false;
+ }
+
+ /**
+ * Verify that any publicly readable directories reachable from
+ * the root directory are not writable. An application should only be
+ * able to write to it's own home directory. World writable directories
+ * are a security hole because they enable a number of different attacks.
+ * <ul>
+ * <li><a href="http://en.wikipedia.org/wiki/Symlink_race">Symlink Races</a></li>
+ * <li>Data destruction by deleting or renaming files you don't own</li>
+ * <li>Data substitution by replacing trusted files with untrusted files</li>
+ * </ul>
+ *
+ * Note: Because not all directories are readable, this is a best-effort
+ * test only. Writable directories within unreadable subdirectories
+ * will NOT be detected by this code.
+ */
+ @LargeTest
+ @Test
+ public void testAllOtherDirectoriesNotWritable() throws Exception {
+ File start = new File("/");
+ Set<File> writableDirs = getWritableDirectoriesAndSubdirectoriesOf(start);
+
+ assertTrue("Found writable directories: " + writableDirs.toString(),
+ writableDirs.isEmpty());
+ }
+
+ private static final Set<String> OTHER_RANDOM_DIRECTORIES = new HashSet<String>(
+ Arrays.asList(
+ "/app-cache",
+ "/app-cache/ciq/socket",
+ "/cache/fotapkg",
+ "/cache/fotapkg/tmp",
+ "/data/_SamsungBnR_",
+ "/data/_SamsungBnR_/BR",
+ "/data/2nd-init",
+ "/data/amit",
+ "/data/anr",
+ "/data/app",
+ "/data/app-private",
+ "/data/backup",
+ "/data/battd",
+ "/data/bootlogo",
+ "/data/btips",
+ "/data/btips/TI",
+ "/data/btips/TI/opp",
+ "/data/cache",
+ "/data/calibration",
+ "/data/clipboard",
+ "/data/clp",
+ "/data/dalvik-cache",
+ "/data/data",
+ "/data/data/.drm",
+ "/data/data/.drm/.wmdrm",
+ "/data/data/cw",
+ "/data/data/com.android.htcprofile",
+ "/data/data/com.android.providers.drm/rights",
+ "/data/data/com.htc.android.qxdm2sd",
+ "/data/data/com.htc.android.qxdm2sd/bin",
+ "/data/data/com.htc.android.qxdm2sd/data",
+ "/data/data/com.htc.android.qxdm2sd/tmp",
+ "/data/data/com.htc.android.netlogger/data",
+ "/data/data/com.htc.messagecs/att",
+ "/data/data/com.htc.messagecs/pdu",
+ "/data/data/com.htc.loggers/bin",
+ "/data/data/com.htc.loggers/data",
+ "/data/data/com.htc.loggers/htclog",
+ "/data/data/com.htc.loggers/tmp",
+ "/data/data/com.htc.loggers/htcghost",
+ "/data/data/com.lge.ers/android",
+ "/data/data/com.lge.ers/arm9",
+ "/data/data/com.lge.ers/kernel",
+ "/data/data/com.lge.wmc",
+ "/data/data/com.redbend.vdmc/lib",
+ "/data/data/recovery",
+ "/data/data/recovery/HTCFOTA",
+ "/data/data/recovery/OMADM",
+ "/data/data/shared",
+ "/data/diag_logs",
+ "/data/dontpanic",
+ "/data/drm",
+ "/data/drm/fwdlock",
+ "/data/drm/IDM",
+ "/data/drm/IDM/HTTP",
+ "/data/drm/rights",
+ "/data/dump",
+ "/data/efslog",
+ "/data/emt",
+ "/data/factory",
+ "/data/fics",
+ "/data/fics/dev",
+ "/data/fota",
+ "/data/gps",
+ "/data/gps/log",
+ "/data/gps/var",
+ "/data/gps/var/run",
+ "/data/gpscfg",
+ "/data/hwvefs",
+ "/data/htcfs",
+ "/data/img",
+ "/data/install",
+ "/data/internal-device",
+ "/data/internal-device/DCIM",
+ "/data/last_alog",
+ "/data/last_klog",
+ "/data/local",
+ "/data/local/logs",
+ "/data/local/logs/kernel",
+ "/data/local/logs/logcat",
+ "/data/local/logs/resetlog",
+ "/data/local/logs/smem",
+ "/data/local/mono",
+ "/data/local/mono/pulse",
+ "/data/local/purple",
+ "/data/local/purple/sound",
+ "/data/local/rights",
+ "/data/local/rwsystag",
+ "/data/local/skel",
+ "/data/local/skel/default",
+ "/data/local/skel/defualt", // Mispelled "defualt" is intentional
+ "/data/local/tmp",
+ "/data/local/tmp/com.nuance.android.vsuite.vsuiteapp",
+ "/data/log",
+ "/data/logger",
+ "/data/logs",
+ "/data/logs/core",
+ "/data/lost+found",
+ "/data/mdl",
+ "/data/misc",
+ "/data/misc/bluetooth",
+ "/data/misc/bluetooth/logs",
+ "/data/misc/dhcp",
+ "/data/misc/lockscreen",
+ "/data/misc/sensor",
+ "/data/misc/webwidgets",
+ "/data/misc/webwidgets/chess",
+ "/data/misc/widgets",
+ "/data/misc/wifi",
+ "/data/misc/wifi/sockets",
+ "/data/misc/wimax",
+ "/data/misc/wimax/sockets",
+ "/data/misc/wminput",
+ "/data/misc/wpa_supplicant",
+ "/data/nv",
+ "/data/nvcam",
+ "/data/panic",
+ "/data/panicreports",
+ "/data/preinstall_md5",
+ "/data/property",
+ "/data/radio",
+ "/data/secure",
+ "/data/security",
+ "/data/sensors",
+ "/data/shared",
+ "/data/simcom",
+ "/data/simcom/btadd",
+ "/data/simcom/simlog",
+ "/data/system",
+ "/data/tmp",
+ "/data/tombstones",
+ "/data/tombstones/ramdump",
+ "/data/tpapi",
+ "/data/tpapi/etc",
+ "/data/tpapi/etc/tpa",
+ "/data/tpapi/etc/tpa/persistent",
+ "/data/tpapi/user.bin",
+ "/data/vpnch",
+ "/data/wapi",
+ "/data/wifi",
+ "/data/wimax",
+ "/data/wimax/log",
+ "/data/wiper",
+ "/data/wpstiles",
+ "/data/xt9",
+ "/dbdata/databases",
+ "/efs/.android",
+ "/mnt/sdcard",
+ "/mnt/usbdrive",
+ "/mnt_ext",
+ "/mnt_ext/badablk2",
+ "/mnt_ext/badablk3",
+ "/mnt_ext/cache",
+ "/mnt_ext/data",
+ "/system/etc/security/drm",
+ "/synthesis/hades",
+ "/synthesis/chimaira",
+ "/synthesis/shdisp",
+ "/synthesis/hdmi",
+ "/tmp"
+ )
+ );
+
+ /**
+ * Verify that directories not discoverable by
+ * testAllOtherDirectoriesNotWritable are not writable. An application
+ * should only be able to write to it's own home directory. World
+ * writable directories are a security hole because they enable a
+ * number of different attacks.
+ * <ul>
+ * <li><a href="http://en.wikipedia.org/wiki/Symlink_race">Symlink Races</a></li>
+ * <li>Data destruction by deleting or renaming files you don't own</li>
+ * <li>Data substitution by replacing trusted files with untrusted files</li>
+ * </ul>
+ *
+ * Because /data and /data/data are not readable, we blindly try to
+ * poke around in there looking for bad directories. There has to be
+ * a better way...
+ */
+ @LargeTest
+ @Test
+ public void testOtherRandomDirectoriesNotWritable() throws Exception {
+ Set<File> writableDirs = new HashSet<File>();
+ for (String dir : OTHER_RANDOM_DIRECTORIES) {
+ File start = new File(dir);
+ writableDirs.addAll(getWritableDirectoriesAndSubdirectoriesOf(start));
+ }
+
+ assertTrue("Found writable directories: " + writableDirs.toString(),
+ writableDirs.isEmpty());
+ }
+
+ @LargeTest
+ @Test
+ public void testReadingSysFilesDoesntFail() throws Exception {
+ ExecutorService executor = Executors.newCachedThreadPool();
+ tryToReadFromAllIn(new File("/sys"), executor);
+ executor.shutdownNow();
+ }
+
+ private static void tryToReadFromAllIn(File dir, ExecutorService executor) throws IOException {
+ assertTrue(dir.isDirectory());
+
+ if (isSymbolicLink(dir)) {
+ // don't examine symbolic links.
+ return;
+ }
+
+ File[] files = dir.listFiles();
+
+ if (files != null) {
+ for (File f : files) {
+ if (f.isDirectory()) {
+ tryToReadFromAllIn(f, executor);
+ } else {
+ tryFileOpenRead(f, executor);
+ }
+ }
+ }
+ }
+
+ private static void tryFileOpenRead(final File f, ExecutorService executor) throws IOException {
+ // Callable requires stack variables to be final.
+ Callable<Boolean> readFile = new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ return tryFileRead(f);
+ }
+ };
+
+ Boolean completed = false;
+ String fileName = null;
+ Future<Boolean> future = null;
+ try {
+ fileName = f.getCanonicalPath();
+
+ future = executor.submit(readFile);
+
+ // Block, waiting no more than set seconds.
+ completed = future.get(3, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ System.out.println("TIMEOUT: " + fileName);
+ } catch (InterruptedException e) {
+ System.out.println("INTERRUPTED: " + fileName);
+ } catch (ExecutionException e) {
+ System.out.println("TASK WAS ABORTED BY EXCEPTION: " + fileName);
+ } catch (IOException e) {
+ // File.getCanonicalPath() will throw this.
+ } finally {
+ if (future != null) {
+ future.cancel(true);
+ }
+ }
+ }
+
+ private static Boolean tryFileRead(File f) {
+ byte[] b = new byte[1024];
+ try {
+ System.out.println("looking at " + f.getCanonicalPath());
+
+ FileInputStream fis = new FileInputStream(f);
+ while((fis.available() != 0) && (fis.read(b) != -1)) {
+ // throw away data
+ }
+
+ fis.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ return true;
+ }
+
+ private static final Set<File> SYS_EXCEPTIONS = new HashSet<File>(
+ Arrays.asList(
+ new File("/sys/kernel/debug/tracing/trace_marker"),
+ new File("/sys/fs/selinux/member"),
+ new File("/sys/fs/selinux/user"),
+ new File("/sys/fs/selinux/relabel"),
+ new File("/sys/fs/selinux/create"),
+ new File("/sys/fs/selinux/access"),
+ new File("/sys/fs/selinux/context"),
+ new File("/sys/fs/selinux/validatetrans")
+ ));
+
+ @LargeTest
+ @Test
+ public void testAllFilesInSysAreNotWritable() throws Exception {
+ Set<File> writable = getAllWritableFilesInDirAndSubDir(new File("/sys"));
+ writable.removeAll(SYS_EXCEPTIONS);
+ assertTrue("Found writable: " + writable.toString(),
+ writable.isEmpty());
+ }
+
+ private static Set<File>
+ getAllWritableFilesInDirAndSubDir(File dir) throws Exception {
+ assertTrue(dir.isDirectory());
+ Set<File> retval = new HashSet<File>();
+
+ if (isSymbolicLink(dir)) {
+ // don't examine symbolic links.
+ return retval;
+ }
+
+ File[] subDirectories = dir.listFiles(new FileFilter() {
+ @Override public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+
+
+ /* recurse into subdirectories */
+ if (subDirectories != null) {
+ for (File f : subDirectories) {
+ retval.addAll(getAllWritableFilesInDirAndSubDir(f));
+ }
+ }
+
+ File[] filesInThisDirectory = dir.listFiles(new FileFilter() {
+ @Override public boolean accept(File pathname) {
+ return pathname.isFile();
+ }
+ });
+ if (filesInThisDirectory == null) {
+ return retval;
+ }
+
+ for (File f: filesInThisDirectory) {
+ if (f.canWrite()) {
+ retval.add(f.getCanonicalFile());
+ }
+ }
+ return retval;
+ }
+
+ @Test
+ public void testSystemMountedRO() throws Exception {
+ StructStatVfs vfs = Os.statvfs("/system");
+ assertTrue("/system is not mounted read-only", (vfs.f_flag & OsConstants.ST_RDONLY) != 0);
+ }
+
+ @Test
+ public void testRootMountedRO() throws Exception {
+ StructStatVfs vfs = Os.statvfs("/");
+ assertTrue("rootfs is not mounted read-only", (vfs.f_flag & OsConstants.ST_RDONLY) != 0);
+ }
+
+ @Test
+ public void testVendorMountedRO() throws Exception {
+ StructStatVfs vfs = Os.statvfs("/vendor");
+ assertTrue("/vendor is not mounted read-only", (vfs.f_flag & OsConstants.ST_RDONLY) != 0);
+ }
+
+ @Test
+ public void testOdmMountedRO() throws Exception {
+ StructStatVfs vfs = Os.statvfs("/odm");
+ assertTrue("/odm is not mounted read-only", (vfs.f_flag & OsConstants.ST_RDONLY) != 0);
+ }
+
+ @Test
+ public void testOemMountedRO() throws Exception {
+ StructStatVfs vfs = Os.statvfs("/oem");
+ assertTrue("/oem is not mounted read-only", (vfs.f_flag & OsConstants.ST_RDONLY) != 0);
+ }
+
+ @Test
+ public void testDataMountedNoSuidNoDev() throws Exception {
+ StructStatVfs vfs = Os.statvfs(getContext().getFilesDir().getAbsolutePath());
+ assertTrue("/data is not mounted NOSUID", (vfs.f_flag & OsConstants.ST_NOSUID) != 0);
+ assertTrue("/data is not mounted NODEV", (vfs.f_flag & OsConstants.ST_NODEV) != 0);
+ }
+
+ @Test
+ public void testAllBlockDevicesAreSecure() throws Exception {
+ Set<File> insecure = getAllInsecureDevicesInDirAndSubdir(new File("/dev"), FileUtils.S_IFBLK);
+ assertTrue("Found insecure block devices: " + insecure.toString(),
+ insecure.isEmpty());
+ }
+
+ @Test
+ public void testDevRandomWorldReadableAndWritable() throws Exception {
+ File f = new File("/dev/random");
+
+ assertTrue(f + " cannot be opened for reading", canOpenForReading(f));
+ assertTrue(f + " cannot be opened for writing", canOpenForWriting(f));
+
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus(f.getPath(), status, false));
+ assertTrue(
+ f + " not world-readable/writable. Actual mode: 0"
+ + Integer.toString(status.mode, 8),
+ (status.mode & 0666) == 0666);
+ }
+
+ @Test
+ public void testDevUrandomWorldReadableAndWritable() throws Exception {
+ File f = new File("/dev/urandom");
+
+ assertTrue(f + " cannot be opened for reading", canOpenForReading(f));
+ assertTrue(f + " cannot be opened for writing", canOpenForWriting(f));
+
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus(f.getPath(), status, false));
+ assertTrue(
+ f + " not world-readable/writable. Actual mode: 0"
+ + Integer.toString(status.mode, 8),
+ (status.mode & 0666) == 0666);
+ }
+
+ @Test
+ public void testProcUUIDReadable() throws Exception {
+ File f = new File("/proc/sys/kernel/random/uuid");
+
+ assertTrue(f + " cannot be opened for reading", canOpenForReading(f));
+ assertFalse(f + " can be opened for writing", canOpenForWriting(f));
+
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus(f.getPath(), status, false));
+ assertTrue(
+ f + " not 0444. Actual mode: 0"
+ + Integer.toString(status.mode, 8),
+ (status.mode & 0666) == 0444);
+ }
+
+ @Test
+ public void testDevHwRandomLockedDown() throws Exception {
+ File f = new File("/dev/hw_random");
+ if (!f.exists()) {
+ // HW RNG is not required to be exposed on all devices.
+ return;
+ }
+
+ // SELinux policy should ensure that the file isn't visible to apps at
+ // all.
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertFalse("stat permitted on " + f + " (SELinux issue?)",
+ FileUtils.getFileStatus(f.getPath(), status, false));
+
+ // Double-check that we really can't read/write the file.
+ assertFalse(f + " can be opened for reading (SELinux issue?)", canOpenForReading(f));
+ assertFalse(f + " can be opened for writing (SELinux issue?)", canOpenForWriting(f));
+ }
+
+ private static boolean canOpenForReading(File f) {
+ try (InputStream in = new FileInputStream(f)) {
+ return true;
+ } catch (IOException expected) {
+ return false;
+ }
+ }
+
+ private static boolean canOpenForWriting(File f) {
+ try (OutputStream out = new FileOutputStream(f)) {
+ return true;
+ } catch (IOException expected) {
+ return false;
+ }
+ }
+
+ @Test
+ public void testFileHasOnlyCapsThrowsOnInvalidCaps() throws Exception {
+ try {
+ // Ensure negative cap id fails.
+ new FileUtils.CapabilitySet()
+ .add(-1)
+ .fileHasOnly("/system/bin/run-as");
+ fail();
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ // Ensure too-large cap throws.
+ new FileUtils.CapabilitySet()
+ .add(OsConstants.CAP_LAST_CAP + 1)
+ .fileHasOnly("/system/bin/run-as");
+ fail();
+ }
+ catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Test that the /system/bin/run-as command has setuid and setgid
+ * attributes set on the file. If these calls fail, debugger
+ * breakpoints for native code will not work as run-as will not
+ * be able to perform required elevated-privilege functionality.
+ */
+ @Test
+ public void testRunAsHasCorrectCapabilities() throws Exception {
+ // ensure file is user and group read/executable
+ String filename = "/system/bin/run-as";
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ assertTrue(FileUtils.getFileStatus(filename, status, false));
+ assertTrue(status.hasModeFlag(FileUtils.S_IRUSR | FileUtils.S_IXUSR));
+ assertTrue(status.hasModeFlag(FileUtils.S_IRGRP | FileUtils.S_IXGRP));
+
+ // ensure file owner/group is set correctly
+ File f = new File(filename);
+ assertFileOwnedBy(f, "root");
+ assertFileOwnedByGroup(f, "shell");
+
+ // ensure file has setuid/setgid enabled
+ assertTrue(FileUtils.hasSetUidCapability(filename));
+ assertTrue(FileUtils.hasSetGidCapability(filename));
+
+ // ensure file has *only* setuid/setgid attributes enabled
+ assertTrue(new FileUtils.CapabilitySet()
+ .add(OsConstants.CAP_SETUID)
+ .add(OsConstants.CAP_SETGID)
+ .fileHasOnly("/system/bin/run-as"));
+ }
+
+ private static Set<File>
+ getAllInsecureDevicesInDirAndSubdir(File dir, int type) throws Exception {
+ assertTrue(dir.isDirectory());
+ Set<File> retval = new HashSet<File>();
+
+ if (isSymbolicLink(dir)) {
+ // don't examine symbolic links.
+ return retval;
+ }
+
+ File[] subDirectories = dir.listFiles(new FileFilter() {
+ @Override public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+
+
+ /* recurse into subdirectories */
+ if (subDirectories != null) {
+ for (File f : subDirectories) {
+ retval.addAll(getAllInsecureDevicesInDirAndSubdir(f, type));
+ }
+ }
+
+ File[] filesInThisDirectory = dir.listFiles();
+ if (filesInThisDirectory == null) {
+ return retval;
+ }
+
+ for (File f: filesInThisDirectory) {
+ FileUtils.FileStatus status = new FileUtils.FileStatus();
+ FileUtils.getFileStatus(f.getAbsolutePath(), status, false);
+ if (status.isOfType(type)) {
+ if (f.canRead() || f.canWrite() || f.canExecute()) {
+ retval.add(f);
+ }
+ if (status.uid == 2000) {
+ // The shell user should not own any devices
+ retval.add(f);
+ }
+
+ // Don't allow devices owned by GIDs
+ // accessible to non-privileged applications.
+ if ((status.gid == 1007) // AID_LOG
+ || (status.gid == 1015) // AID_SDCARD_RW
+ || (status.gid == 1023) // AID_MEDIA_RW
+ || (status.gid == 1028) // AID_SDCARD_R
+ || (status.gid == 2000)) // AID_SHELL
+ {
+ if (status.hasModeFlag(FileUtils.S_IRGRP)
+ || status.hasModeFlag(FileUtils.S_IWGRP)
+ || status.hasModeFlag(FileUtils.S_IXGRP))
+ {
+ retval.add(f);
+ }
+ }
+ }
+ }
+ return retval;
+ }
+
+ private Set<File> getWritableDirectoriesAndSubdirectoriesOf(File dir) throws Exception {
+ Set<File> retval = new HashSet<File>();
+ if (!dir.isDirectory()) {
+ return retval;
+ }
+
+ if (isSymbolicLink(dir)) {
+ // don't examine symbolic links.
+ return retval;
+ }
+
+ String myHome = getContext().getApplicationInfo().dataDir;
+ String thisDir = dir.getCanonicalPath();
+ if (thisDir.startsWith(myHome)) {
+ // Don't examine directories within our home directory.
+ // We expect these directories to be writable.
+ return retval;
+ }
+
+ if (isDirectoryWritable(dir)) {
+ retval.add(dir);
+ }
+
+ File[] subFiles = dir.listFiles();
+ if (subFiles == null) {
+ return retval;
+ }
+
+ for (File f : subFiles) {
+ retval.addAll(getWritableDirectoriesAndSubdirectoriesOf(f));
+ }
+
+ return retval;
+ }
+
+ private static boolean isSymbolicLink(File f) throws IOException {
+ return !f.getAbsolutePath().equals(f.getCanonicalPath());
+ }
+
+}
diff --git a/tests/cts/permission/src/android/permission/cts/FileUtils.java b/tests/cts/permission/src/android/permission/cts/FileUtils.java
new file mode 100644
index 000000000..0743cd30a
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/FileUtils.java
@@ -0,0 +1,128 @@
+package android.permission.cts;
+
+/*
+ * Copyright (C) 2010 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.
+ */
+
+import android.system.OsConstants;
+
+import com.google.common.primitives.Ints;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/** Bits and pieces copied from hidden API of android.os.FileUtils. */
+public class FileUtils {
+
+ public static final int S_IFMT = 0170000;
+ public static final int S_IFSOCK = 0140000;
+ public static final int S_IFLNK = 0120000;
+ public static final int S_IFREG = 0100000;
+ public static final int S_IFBLK = 0060000;
+ public static final int S_IFDIR = 0040000;
+ public static final int S_IFCHR = 0020000;
+ public static final int S_IFIFO = 0010000;
+
+ public static final int S_ISUID = 0004000;
+ public static final int S_ISGID = 0002000;
+ public static final int S_ISVTX = 0001000;
+
+ public static final int S_IRWXU = 00700;
+ public static final int S_IRUSR = 00400;
+ public static final int S_IWUSR = 00200;
+ public static final int S_IXUSR = 00100;
+
+ public static final int S_IRWXG = 00070;
+ public static final int S_IRGRP = 00040;
+ public static final int S_IWGRP = 00020;
+ public static final int S_IXGRP = 00010;
+
+ public static final int S_IRWXO = 00007;
+ public static final int S_IROTH = 00004;
+ public static final int S_IWOTH = 00002;
+ public static final int S_IXOTH = 00001;
+
+ static {
+ System.loadLibrary("ctspermission_jni");
+ }
+
+ public static class FileStatus {
+
+ public int dev;
+ public int ino;
+ public int mode;
+ public int nlink;
+ public int uid;
+ public int gid;
+ public int rdev;
+ public long size;
+ public int blksize;
+ public long blocks;
+ public long atime;
+ public long mtime;
+ public long ctime;
+
+ public boolean hasModeFlag(int flag) {
+ if (((S_IRWXU | S_IRWXG | S_IRWXO) & flag) != flag) {
+ throw new IllegalArgumentException("Inappropriate flag " + flag);
+ }
+ return (mode & flag) == flag;
+ }
+
+ public boolean isOfType(int type) {
+ if ((type & S_IFMT) != type) {
+ throw new IllegalArgumentException("Unknown type " + type);
+ }
+ return (mode & S_IFMT) == type;
+ }
+ }
+
+ public static class CapabilitySet {
+
+ private final Set<Integer> mCapabilities = new HashSet<Integer>();
+
+ public CapabilitySet add(int capability) {
+ if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
+ throw new IllegalArgumentException(String.format(
+ "capability id %d out of valid range", capability));
+ }
+ mCapabilities.add(capability);
+ return this;
+ }
+
+ private native static boolean fileHasOnly(String path,
+ int[] capabilities);
+
+ public boolean fileHasOnly(String path) {
+ return fileHasOnly(path, Ints.toArray(mCapabilities));
+ }
+ }
+
+ /**
+ * @param path of the file to stat
+ * @param status object to set the fields on
+ * @param statLinks or don't stat links (lstat vs stat)
+ * @return whether or not we were able to stat the file
+ */
+ public native static boolean getFileStatus(String path, FileStatus status, boolean statLinks);
+
+ public native static String getUserName(int uid);
+
+ public native static String getGroupName(int gid);
+
+ public native static boolean hasSetUidCapability(String path);
+
+ public native static boolean hasSetGidCapability(String path);
+}
diff --git a/tests/cts/permission/src/android/permission/cts/IgnoreAllTestsRule.java b/tests/cts/permission/src/android/permission/cts/IgnoreAllTestsRule.java
new file mode 100644
index 000000000..45288bd48
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/IgnoreAllTestsRule.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+/**
+ * A {@link org.junit.Rule} that will cause all tests in the class
+ * to be ignored if the argument to the constructor is true.
+ */
+public class IgnoreAllTestsRule implements MethodRule {
+
+ private boolean mIgnore;
+
+ /**
+ * Creates a new IgnoreAllTestsRule
+ * @param ignore If true, all tests in the class will be ignored. If false, this rule will
+ * do nothing.
+ */
+ public IgnoreAllTestsRule(boolean ignore) {
+ mIgnore = ignore;
+ }
+
+ @Override
+ public Statement apply(Statement base, FrameworkMethod method, Object target) {
+ if (mIgnore) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ }
+ };
+ } else {
+ return base;
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/LocationAccessCheckTest.java b/tests/cts/permission/src/android/permission/cts/LocationAccessCheckTest.java
new file mode 100644
index 000000000..7f5cf137c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/LocationAccessCheckTest.java
@@ -0,0 +1,851 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
+import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
+import static android.content.Context.BIND_AUTO_CREATE;
+import static android.content.Context.BIND_NOT_FOREGROUND;
+import static android.location.Criteria.ACCURACY_FINE;
+import static android.os.Process.myUserHandle;
+import static android.provider.Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS;
+import static android.provider.Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.waitForBroadcasts;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AppOpsManager;
+import android.app.PendingIntent;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Process;
+import android.permission.cts.appthataccesseslocation.IAccessLocationOnCommand;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.SystemUserOnly;
+import android.platform.test.rule.ScreenRecordRule;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
+import com.android.compatibility.common.util.mainline.MainlineModule;
+import com.android.compatibility.common.util.mainline.ModuleDetector;
+import com.android.modules.utils.build.SdkLevel;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Tests the {@code LocationAccessCheck} in permission controller.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot set system settings as instant app. Also we never show a location "
+ + "access check notification for instant apps.")
+@ScreenRecordRule.ScreenRecord
+@FlakyTest
+public class LocationAccessCheckTest {
+
+ private static final String LOG_TAG = LocationAccessCheckTest.class.getSimpleName();
+
+ private static final String TEST_APP_PKG = "android.permission.cts.appthataccesseslocation";
+ private static final String TEST_APP_LABEL = "CtsLocationAccess";
+ private static final String TEST_APP_SERVICE = TEST_APP_PKG + ".AccessLocationOnCommand";
+ private static final String TEST_APP_LOCATION_BG_ACCESS_APK =
+ "/data/local/tmp/cts-permission/CtsAppThatAccessesLocationOnCommand.apk";
+ private static final String TEST_APP_LOCATION_FG_ACCESS_APK =
+ "/data/local/tmp/cts-permission/AppThatDoesNotHaveBgLocationAccess.apk";
+ private static final String ACTION_SET_UP_LOCATION_ACCESS_CHECK =
+ "com.android.permissioncontroller.action.SET_UP_LOCATION_ACCESS_CHECK";
+ private static final int LOCATION_ACCESS_CHECK_JOB_ID = 0;
+ private static final int LOCATION_ACCESS_CHECK_NOTIFICATION_ID = 0;
+
+ /**
+ * Whether to show location access check notifications.
+ */
+ private static final String PROPERTY_LOCATION_ACCESS_CHECK_ENABLED =
+ "location_access_check_enabled";
+ private static final String PROPERTY_LOCATION_ACCESS_CHECK_DELAY_MILLIS =
+ "location_access_check_delay_millis";
+ private static final String PROPERTY_LOCATION_ACCESS_PERIODIC_INTERVAL_MILLIS =
+ "location_access_check_periodic_interval_millis";
+ private static final String PROPERTY_BG_LOCATION_CHECK_ENABLED = "bg_location_check_is_enabled";
+
+ private static final long UNEXPECTED_TIMEOUT_MILLIS = 10000;
+ private static final long EXPECTED_TIMEOUT_MILLIS = 15000;
+ private static final long LOCATION_ACCESS_TIMEOUT_MILLIS = 15000;
+
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private static final ActivityManager sActivityManager =
+ sContext.getSystemService(ActivityManager.class);
+ private static final PackageManager sPackageManager = sContext.getPackageManager();
+ private static final AppOpsManager sAppOpsManager =
+ sContext.getSystemService(AppOpsManager.class);
+ private static final LocationManager sLocationManager =
+ sContext.getSystemService(LocationManager.class);
+ private static final UiAutomation sUiAutomation = InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation();
+
+ private static final String PERMISSION_CONTROLLER_PKG = sContext.getPackageManager()
+ .getPermissionControllerPackageName();
+ private static final String LocationAccessCheckOnBootReceiver =
+ "com.android.permissioncontroller.permission.service"
+ + ".LocationAccessCheck$SetupPeriodicBackgroundLocationAccessCheck";
+
+
+ /**
+ * The result of {@link #assumeCanGetFineLocation()}, so we don't have to run it over and over
+ * again.
+ */
+ private static Boolean sCanAccessFineLocation = null;
+
+ private static ServiceConnection sConnection;
+ private static IAccessLocationOnCommand sLocationAccessor;
+
+ private static void assumeNotPlayManaged() throws Exception {
+ assumeFalse(ModuleDetector.moduleIsPlayManaged(
+ sContext.getPackageManager(), MainlineModule.PERMISSION_CONTROLLER));
+ }
+
+ @Rule
+ public final ScreenRecordRule mScreenRecordRule = new ScreenRecordRule(false, false);
+
+ // Override location access check flag
+ @Rule
+ public DeviceConfigStateChangerRule mPrivacyDeviceConfig =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_LOCATION_ACCESS_CHECK_ENABLED,
+ Boolean.toString(true));
+
+ // Override SafetyCenter enabled flag
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigSafetyCenterEnabled =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyCenterUtils.PROPERTY_SAFETY_CENTER_ENABLED,
+ Boolean.toString(true));
+
+ // Override BG location enabled flag
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigBgLocationCheckEnabled =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_BG_LOCATION_CHECK_ENABLED,
+ Boolean.toString(true));
+
+ // Override general notification interval
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigBgCheckIntervalMillis =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_LOCATION_ACCESS_PERIODIC_INTERVAL_MILLIS,
+ "100");
+
+ // Override general delay interval
+ @Rule
+ public DeviceConfigStateChangerRule sPrivacyDeviceConfigBgCheckDelayMillis =
+ new DeviceConfigStateChangerRule(sContext,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_LOCATION_ACCESS_CHECK_DELAY_MILLIS,
+ "50");
+
+ private static boolean sWasLocationEnabled = true;
+
+ @BeforeClass
+ public static void beforeClassSetup() throws Exception {
+ reduceDelays();
+ allowNotificationAccess();
+ installBackgroundAccessApp();
+ runWithShellPermissionIdentity(() -> {
+ sWasLocationEnabled = sLocationManager.isLocationEnabled();
+ if (!sWasLocationEnabled) {
+ sLocationManager.setLocationEnabledForUser(true, Process.myUserHandle());
+ }
+ });
+ }
+
+ /**
+ * Change settings so that permission controller can show location access notifications more
+ * often.
+ */
+ public static void reduceDelays() {
+ runWithShellPermissionIdentity(() -> {
+ ContentResolver cr = sContext.getContentResolver();
+ // New settings will be applied in when permission controller is reset
+ Settings.Secure.putLong(cr, LOCATION_ACCESS_CHECK_INTERVAL_MILLIS, 100);
+ Settings.Secure.putLong(cr, LOCATION_ACCESS_CHECK_DELAY_MILLIS, 50);
+ });
+ }
+
+ @AfterClass
+ public static void cleanupAfterClass() throws Throwable {
+ resetDelays();
+ uninstallTestApp();
+ disallowNotificationAccess();
+ runWithShellPermissionIdentity(() -> {
+ if (!sWasLocationEnabled) {
+ sLocationManager.setLocationEnabledForUser(false, Process.myUserHandle());
+ }
+ });
+ }
+
+ /**
+ * Reset settings so that permission controller runs normally.
+ */
+ public static void resetDelays() throws Throwable {
+ runWithShellPermissionIdentity(() -> {
+ ContentResolver cr = sContext.getContentResolver();
+ Settings.Secure.resetToDefaults(cr, LOCATION_ACCESS_CHECK_INTERVAL_MILLIS);
+ Settings.Secure.resetToDefaults(cr, LOCATION_ACCESS_CHECK_DELAY_MILLIS);
+ });
+ }
+
+ /**
+ * Connected to {@value #TEST_APP_PKG} and make it access the location in the background
+ */
+ private void accessLocation() throws Throwable {
+ if (sConnection == null || sLocationAccessor == null) {
+ bindService();
+ }
+
+ long beforeAccess = System.currentTimeMillis();
+ // Wait a little to avoid raciness in timing between threads
+ Thread.sleep(1000);
+
+ // Try again until binder call goes though. It might not go through if the sLocationAccessor
+ // is not bound yet
+ eventually(() -> {
+ assertNotNull(sLocationAccessor);
+ sLocationAccessor.accessLocation();
+ }, EXPECTED_TIMEOUT_MILLIS);
+
+ // Wait until the access is recorded
+ eventually(() -> {
+ List<AppOpsManager.PackageOps> ops = runWithShellPermissionIdentity(
+ () -> sAppOpsManager.getOpsForPackage(
+ sPackageManager.getPackageUid(TEST_APP_PKG, 0), TEST_APP_PKG,
+ OPSTR_FINE_LOCATION));
+
+ // Background access must have happened after "beforeAccess"
+ assertTrue(ops.get(0).getOps().get(0).getLastAccessBackgroundTime(OP_FLAGS_ALL_TRUSTED)
+ >= beforeAccess);
+ }, EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ /**
+ * A {@link java.util.concurrent.Callable} that can throw a {@link Throwable}
+ */
+ private interface ThrowingCallable<T> {
+ T call() throws Throwable;
+ }
+
+ /**
+ * A {@link Runnable} that can throw a {@link Throwable}
+ */
+ private interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+
+ /**
+ * Make sure that a {@link ThrowingRunnable} eventually finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingRunnable} to run.
+ * @param timeout the maximum time to wait
+ */
+ public static void eventually(@NonNull ThrowingRunnable r, long timeout) throws Throwable {
+ eventually(() -> {
+ r.run();
+ return 0;
+ }, timeout);
+ }
+
+ /**
+ * Make sure that a {@link ThrowingCallable} eventually finishes without throwing a {@link
+ * Exception}.
+ *
+ * @param r The {@link ThrowingCallable} to run.
+ * @param timeout the maximum time to wait
+ * @return the return value from the callable
+ * @throws NullPointerException If the return value never becomes non-null
+ */
+ public static <T> T eventually(@NonNull ThrowingCallable<T> r, long timeout) throws Throwable {
+ long start = System.currentTimeMillis();
+
+ while (true) {
+ try {
+ T res = r.call();
+ if (res == null) {
+ throw new NullPointerException("No result");
+ }
+
+ return res;
+ } catch (Throwable e) {
+ if (System.currentTimeMillis() - start < timeout) {
+ Log.d(LOG_TAG, "Ignoring exception", e);
+
+ Thread.sleep(500);
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ /**
+ * Clear all data of a package including permissions and files.
+ *
+ * @param pkg The name of the package to be cleared
+ */
+ private static void clearPackageData(@NonNull String pkg) {
+ unbindService();
+ runShellCommand("pm clear --user -2 " + pkg);
+ }
+
+ private static boolean isJobReady() {
+ String jobStatus = runShellCommand("cmd jobscheduler get-job-state -u "
+ + Process.myUserHandle().getIdentifier() + " " + PERMISSION_CONTROLLER_PKG
+ + " " + LOCATION_ACCESS_CHECK_JOB_ID);
+ return jobStatus.contains("waiting");
+ }
+
+ /**
+ * Force a run of the location check.
+ */
+ private static void runLocationCheck() throws Throwable {
+ if (!isJobReady()) {
+ PermissionUtils.scheduleJob(sUiAutomation, PERMISSION_CONTROLLER_PKG,
+ LOCATION_ACCESS_CHECK_JOB_ID, EXPECTED_TIMEOUT_MILLIS,
+ ACTION_SET_UP_LOCATION_ACCESS_CHECK, LocationAccessCheckOnBootReceiver);
+ }
+
+ TestUtils.awaitJobUntilRequestedState(
+ PERMISSION_CONTROLLER_PKG,
+ LOCATION_ACCESS_CHECK_JOB_ID,
+ EXPECTED_TIMEOUT_MILLIS,
+ sUiAutomation,
+ "waiting"
+ );
+
+ TestUtils.runJobAndWaitUntilCompleted(
+ PERMISSION_CONTROLLER_PKG,
+ LOCATION_ACCESS_CHECK_JOB_ID,
+ EXPECTED_TIMEOUT_MILLIS,
+ sUiAutomation
+ );
+ }
+
+ /**
+ * Get a location access notification that is currently visible.
+ *
+ * @param cancelNotification if {@code true} the notification is canceled inside this method
+ * @return The notification or {@code null} if there is none
+ */
+ private StatusBarNotification getNotification(boolean cancelNotification) throws Throwable {
+ return CtsNotificationListenerServiceUtils.getNotificationForPackageAndId(
+ PERMISSION_CONTROLLER_PKG, LOCATION_ACCESS_CHECK_NOTIFICATION_ID,
+ cancelNotification);
+ }
+
+ /**
+ * Grant a permission to the {@value #TEST_APP_PKG}.
+ *
+ * @param permission The permission to grant
+ */
+ private void grantPermissionToTestApp(@NonNull String permission) {
+ sUiAutomation.grantRuntimePermission(TEST_APP_PKG, permission);
+ }
+
+ /**
+ * Register {@link CtsNotificationListenerService}.
+ */
+ public static void allowNotificationAccess() {
+ runShellCommand("cmd notification allow_listener " + (new ComponentName(sContext,
+ CtsNotificationListenerService.class).flattenToString()));
+ }
+
+ public static void installBackgroundAccessApp() throws Exception {
+ String output =
+ runShellCommandOrThrow("pm install -r -g " + TEST_APP_LOCATION_BG_ACCESS_APK);
+ assertTrue(output.contains("Success"));
+ // Wait for user sensitive to be updated, which is checked by LocationAccessCheck.
+ Thread.sleep(5000);
+ }
+
+ public static void uninstallTestApp() {
+ unbindService();
+ runShellCommand("pm uninstall " + TEST_APP_PKG);
+ }
+
+ private static void unbindService() {
+ if (sConnection != null) {
+ sContext.unbindService(sConnection);
+ }
+ sConnection = null;
+ sLocationAccessor = null;
+ }
+
+ private void setDeviceConfigProperty(
+ @NonNull String propertyName,
+ @NonNull String value) {
+ runWithShellPermissionIdentity(() -> {
+ boolean valueWasSet = DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ propertyName,
+ value,
+ false);
+ if (!valueWasSet) {
+ throw new IllegalStateException("Could not set " + propertyName + " to " + value);
+ }
+ });
+ }
+
+
+ private static void installForegroundAccessApp() throws Exception {
+ unbindService();
+ runShellCommandOrThrow("pm install -r -g " + TEST_APP_LOCATION_FG_ACCESS_APK);
+ // Wait for user sensitive to be updated, which is checked by LocationAccessCheck.
+ Thread.sleep(5000);
+ }
+
+ /**
+ * Skip each test for low ram device
+ */
+ public void assumeIsNotLowRamDevice() {
+ assumeFalse(sActivityManager.isLowRamDevice());
+ }
+
+ public void wakeUpAndDismissKeyguard() {
+ runShellCommand("input keyevent KEYCODE_WAKEUP");
+ runShellCommand("wm dismiss-keyguard");
+ }
+
+ public void bindService() {
+ sConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ sLocationAccessor = IAccessLocationOnCommand.Stub.asInterface(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ sConnection = null;
+ sLocationAccessor = null;
+ }
+ };
+
+ Intent testAppService = new Intent();
+ testAppService.setComponent(new ComponentName(TEST_APP_PKG, TEST_APP_SERVICE));
+
+ sContext.bindService(testAppService, sConnection, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND);
+ }
+
+ @Before
+ public void beforeEachTestSetup() throws Throwable {
+ assumeIsNotLowRamDevice();
+ wakeUpAndDismissKeyguard();
+ bindService();
+ resetPermissionControllerBeforeEachTest();
+ bypassBatterySavingRestrictions();
+ assumeCanGetFineLocation();
+ }
+
+ /**
+ * Reset the permission controllers state before each test
+ */
+ public void resetPermissionControllerBeforeEachTest() throws Throwable {
+ // Has to be before resetPermissionController to make sure enablement time is the reset time
+ // of permission controller
+ enableLocationAccessCheck();
+
+ resetPermissionController();
+
+ eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ // Reset job scheduler stats (to allow more jobs to be run)
+ runShellCommand(
+ "cmd jobscheduler reset-execution-quota -u " + myUserHandle().getIdentifier() + " "
+ + PERMISSION_CONTROLLER_PKG);
+ runShellCommand("cmd jobscheduler reset-schedule-quota");
+ }
+
+ public void bypassBatterySavingRestrictions() {
+ runShellCommand("cmd tare set-vip " + myUserHandle().getIdentifier()
+ + " " + PERMISSION_CONTROLLER_PKG + " true");
+ }
+
+ /**
+ * Enable location access check
+ */
+ public void enableLocationAccessCheck() throws Throwable {
+ setDeviceConfigProperty(PROPERTY_LOCATION_ACCESS_CHECK_ENABLED,
+ "true");
+ // Run a location access check to update enabled state inside permission controller
+ runLocationCheck();
+ }
+
+ /**
+ * Disable location access check
+ */
+ private void disableLocationAccessCheck() throws Throwable {
+ setDeviceConfigProperty(PROPERTY_LOCATION_ACCESS_CHECK_ENABLED,
+ "false");
+ // Run a location access check to update enabled state inside permission controller
+ runLocationCheck();
+ }
+
+ /**
+ * Make sure fine location can be accessed at all.
+ */
+ public void assumeCanGetFineLocation() {
+ if (sCanAccessFineLocation == null) {
+ Criteria crit = new Criteria();
+ crit.setAccuracy(ACCURACY_FINE);
+
+ CountDownLatch locationCounter = new CountDownLatch(1);
+ sContext.getSystemService(LocationManager.class).requestSingleUpdate(crit,
+ new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ locationCounter.countDown();
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ }
+ }, Looper.getMainLooper());
+
+
+ try {
+ sCanAccessFineLocation = locationCounter.await(LOCATION_ACCESS_TIMEOUT_MILLIS,
+ MILLISECONDS);
+ } catch (InterruptedException ignored) {
+ }
+ }
+
+ assumeTrue(sCanAccessFineLocation);
+ }
+
+ /**
+ * Reset the permission controllers state.
+ */
+ private static void resetPermissionController() throws Throwable {
+ unbindService();
+ PermissionUtils.resetPermissionControllerJob(sUiAutomation, PERMISSION_CONTROLLER_PKG,
+ LOCATION_ACCESS_CHECK_JOB_ID, 45000,
+ ACTION_SET_UP_LOCATION_ACCESS_CHECK, LocationAccessCheckOnBootReceiver);
+ }
+
+ /**
+ * Unregister {@link CtsNotificationListenerService}.
+ */
+ public static void disallowNotificationAccess() {
+ runShellCommand("cmd notification disallow_listener " + (new ComponentName(sContext,
+ CtsNotificationListenerService.class)).flattenToString());
+ }
+
+ @After
+ public void cleanupAfterEachTest() throws Throwable {
+ resetPrivacyConfig();
+ locationUnbind();
+ resetBatterySavingRestrictions();
+ }
+
+ /**
+ * Reset location access check
+ */
+ public void resetPrivacyConfig() throws Throwable {
+ // Run a location access check to update enabled state inside permission controller
+ runLocationCheck();
+ }
+
+ public void locationUnbind() throws Throwable {
+ unbindService();
+ }
+
+ public void resetBatterySavingRestrictions() {
+ runShellCommand("cmd tare set-vip " + myUserHandle().getIdentifier()
+ + " " + PERMISSION_CONTROLLER_PKG + " default");
+ }
+
+ @Test
+ public void notificationIsShown() throws Throwable {
+ accessLocation();
+ runLocationCheck();
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void notificationIsShownOnlyOnce() throws Throwable {
+ assumeNotPlayManaged();
+
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+ accessLocation();
+ runLocationCheck();
+
+ assertNull(getNotification(true));
+ }
+
+ @SystemUserOnly(reason = "b/172259935")
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void notificationIsShownAgainAfterClear() throws Throwable {
+ assumeNotPlayManaged();
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+ clearPackageData(TEST_APP_PKG);
+
+ // Wait until package is cleared and permission controller has cleared the state
+ Thread.sleep(10000);
+ waitForBroadcasts();
+
+ // Clearing removed the permissions, hence grant them again
+ grantPermissionToTestApp(ACCESS_FINE_LOCATION);
+ grantPermissionToTestApp(ACCESS_BACKGROUND_LOCATION);
+
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @SystemUserOnly(reason = "b/172259935")
+ @Test
+ public void notificationIsShownAgainAfterUninstallAndReinstall() throws Throwable {
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+ uninstallTestApp();
+
+ // Wait until package permission controller has cleared the state
+ Thread.sleep(2000);
+
+ installBackgroundAccessApp();
+ waitForBroadcasts();
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void removeNotificationOnUninstall() throws Throwable {
+ assumeNotPlayManaged();
+
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(false)), EXPECTED_TIMEOUT_MILLIS);
+
+ uninstallTestApp();
+ // wait for permission controller (broadcast receiver) to clean up things
+ Thread.sleep(5000);
+ waitForBroadcasts();
+
+ try {
+ eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+ } finally {
+ installBackgroundAccessApp();
+ }
+ }
+
+ @Test
+ public void notificationIsNotShownAfterAppDoesNotRequestLocationAnymore() throws Throwable {
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+
+ // Update to app to a version that does not request permission anymore
+ installForegroundAccessApp();
+
+ try {
+ resetPermissionController();
+
+ runLocationCheck();
+
+ // We don't expect a notification, but try to trigger one anyway
+ assertNull(getNotification(false));
+ } finally {
+ installBackgroundAccessApp();
+ }
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void noNotificationIfFeatureDisabled() throws Throwable {
+ assumeNotPlayManaged();
+
+ disableLocationAccessCheck();
+
+ accessLocation();
+ runLocationCheck();
+
+ assertNull(getNotification(false));
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void notificationOnlyForAccessesSinceFeatureWasEnabled() throws Throwable {
+ assumeNotPlayManaged();
+
+ disableLocationAccessCheck();
+
+ accessLocation();
+ runLocationCheck();
+
+ // No notification expected for accesses before enabling the feature
+ assertNull(getNotification(false));
+
+ enableLocationAccessCheck();
+ Thread.sleep(2000);
+
+ // Trigger update of location enable time. In the real world it enabling happens on the
+ // first location check. I.e. accesses before this location check are ignored.
+ runLocationCheck();
+
+ // No notification expected for accesses before enabling the feature (even after feature is
+ // enabled now)
+ assertNull(getNotification(false));
+
+ // Notification expected for access after enabling the feature
+ accessLocation();
+ runLocationCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void noNotificationIfBlamerNotSystemOrLocationProvider() throws Throwable {
+ assumeNotPlayManaged();
+
+ // Blame the app for access from an untrusted for notification purposes package.
+ runWithShellPermissionIdentity(() -> {
+ AppOpsManager appOpsManager = sContext.getSystemService(AppOpsManager.class);
+ appOpsManager.noteProxyOpNoThrow(OPSTR_FINE_LOCATION, TEST_APP_PKG,
+ sContext.getPackageManager().getPackageUid(TEST_APP_PKG, 0));
+ });
+ runLocationCheck();
+
+ assertNull(getNotification(false));
+ }
+
+ @Test
+ // Mark as flaky until b/286874765 is fixed
+ @FlakyTest
+ @MtsIgnore
+ @AsbSecurityTest(cveBugId = 141028068)
+ public void testOpeningLocationSettingsDoesNotTriggerAccess() throws Throwable {
+ assumeNotPlayManaged();
+
+ Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ sContext.startActivity(intent);
+
+ runLocationCheck();
+ assertNull(getNotification(false));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ public void notificationOnClickOpensSafetyCenter() throws Throwable {
+ assumeTrue(SafetyCenterUtils.deviceSupportsSafetyCenter(sContext));
+ accessLocation();
+ runLocationCheck();
+
+ StatusBarNotification currentNotification = eventually(() -> {
+ StatusBarNotification notification = getNotification(false);
+ assertNotNull(notification);
+ return notification;
+ }, EXPECTED_TIMEOUT_MILLIS);
+
+ // Verify content intent
+ PendingIntent contentIntent = currentNotification.getNotification().contentIntent;
+ if (SdkLevel.isAtLeastU()) {
+ contentIntent.send(null, 0, null, null, null, null,
+ ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle());
+ } else {
+ contentIntent.send();
+ }
+
+ SafetyCenterUtils.assertSafetyCenterStarted();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/MainlineNetworkStackPermissionTest.java b/tests/cts/permission/src/android/permission/cts/MainlineNetworkStackPermissionTest.java
new file mode 100644
index 000000000..adac0befa
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/MainlineNetworkStackPermissionTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class MainlineNetworkStackPermissionTest{
+ private final Context mContext = InstrumentationRegistry.getContext();
+
+ /**
+ * Test that a package defining android.permission.MAINLINE_NETWORK_STACK is installed,
+ * and is a system package
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot access PackageManager#getPermissionInfo")
+ public void testPackageWithMainlineNetworkStackPermission() throws Exception {
+ final PackageManager packageManager = mContext.getPackageManager();
+ assertNotNull("Unable to find PackageManager.", packageManager);
+
+ final PermissionInfo permissioninfo =
+ packageManager.getPermissionInfo(PERMISSION_MAINLINE_NETWORK_STACK, 0);
+ assertNotNull("Network stack permission is not defined.", permissioninfo);
+
+ PackageInfo packageInfo = packageManager.getPackageInfo(permissioninfo.packageName,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_PERMISSIONS);
+ assertNotNull("Package defining the network stack permission is not a system package.",
+ packageInfo.permissions);
+
+ for (PermissionInfo permission : packageInfo.permissions) {
+ if (PERMISSION_MAINLINE_NETWORK_STACK.equals(permission.name)) {
+ return;
+ }
+ }
+
+ fail("Expect a system package defining " + PERMISSION_MAINLINE_NETWORK_STACK
+ + " is installed.");
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/MinMaxSdkVersionTest.kt b/tests/cts/permission/src/android/permission/cts/MinMaxSdkVersionTest.kt
new file mode 100644
index 000000000..6a9046054
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/MinMaxSdkVersionTest.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.permission.cts
+
+import android.app.Instrumentation
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.permission.cts.PermissionUtils.install
+import android.platform.test.annotations.AppModeFull
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import androidx.test.uiautomator.UiDevice
+import com.android.compatibility.common.util.CddTest
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@CddTest(requirement = "9.1/C-0-1")
+@AppModeFull(reason = "Instant apps cannot read state of other packages.")
+class MinMaxSdkVersionTest {
+ private val mInstrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private var mUiDevice: UiDevice? = null
+ private var mContext: Context? = null
+
+ @Before
+ fun setup() {
+ mUiDevice = UiDevice.getInstance(mInstrumentation)
+ mContext = mInstrumentation?.targetContext
+ }
+
+ @Test
+ fun givenMinSdkVersionInRangeThenPermissionIsRequested() {
+ install(TEST_APP_PATH)
+
+ Assert.assertTrue(appRequestsPermission(MINSDK_LT_DEVICESDK))
+ }
+
+ @Test
+ fun givenMinSdkVersionOutOfRangeThenPermissionIsNotRequested() {
+ install(TEST_APP_PATH)
+
+ Assert.assertFalse(appRequestsPermission(MINSDK_GT_DEVICESDK))
+ }
+
+ @Test
+ fun givenMaxSdkVersionInRangeThenPermissionIsRequested() {
+ install(TEST_APP_PATH)
+
+ Assert.assertTrue(appRequestsPermission(MAXSDK_GT_DEVICESDK))
+ }
+
+ @Test
+ fun givenMaxSdkVersionOutOfRangeThenPermissionIsNotRequested() {
+ install(TEST_APP_PATH)
+
+ Assert.assertFalse(appRequestsPermission(MAXSDK_LT_DEVICESDK))
+ }
+
+ private fun appRequestsPermission(permName: String): Boolean {
+ val packageInfo = mContext!!.packageManager.getPackageInfo(
+ TEST_APP_PKG_NAME, PackageManager.GET_PERMISSIONS)
+ return packageInfo.requestedPermissions.any { it == permName }
+ }
+
+ companion object {
+ private const val TEST_APP_NAME =
+ "CtsAppThatRequestsMultiplePermissionsWithMinMaxSdk.apk"
+ private const val TMP_DIR = "/data/local/tmp/cts-permission/"
+ private const val TEST_APP_PATH = TMP_DIR + TEST_APP_NAME
+ private const val TEST_APP_PKG_NAME = "android.permission.cts.appthatrequestpermission"
+ private const val CUSTOM_PERMS = "$TEST_APP_PKG_NAME.permissions"
+ private const val MINSDK_LT_DEVICESDK = "$CUSTOM_PERMS.MINSDK_LT_DEVICESDK"
+ private const val MINSDK_GT_DEVICESDK = "$CUSTOM_PERMS.MINSDK_GT_DEVICESDK"
+ private const val MAXSDK_LT_DEVICESDK = "$CUSTOM_PERMS.MAXSDK_LT_DEVICESDK"
+ private const val MAXSDK_GT_DEVICESDK = "$CUSTOM_PERMS.MAXSDK_GT_DEVICESDK"
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
new file mode 100644
index 000000000..d4ad2ad04
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NearbyDevicesPermissionTest.java
@@ -0,0 +1,307 @@
+/*
+ * 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.revokePermission;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import android.bluetooth.cts.EnableBluetoothRule;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.EnableLocationRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests the behavior of the
+ * {@link android.Manifest.permission_group#NEARBY_DEVICES} permission group
+ * under various permutations of grant states.
+ *
+ * Note that some tests will be recognized as known failures with the new permission subsystem
+ * until b/273999500 is fixed.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+public class NearbyDevicesPermissionTest {
+ private static final String TEST_APP_PKG = "android.permission.cts.appthatrequestpermission";
+ private static final String TEST_APP_AUTHORITY = "appthatrequestpermission";
+ private static final String DISAVOWAL_APP_PKG = "android.permission.cts.appneverforlocation";
+
+ private static final String TMP_DIR = "/data/local/tmp/cts-permission/";
+ private static final String APK_BLUETOOTH_30 = TMP_DIR
+ + "CtsAppThatRequestsBluetoothPermission30.apk";
+ private static final String APK_BLUETOOTH_31 = TMP_DIR
+ + "CtsAppThatRequestsBluetoothPermission31.apk";
+ private static final String APK_BLUETOOTH_NEVER_FOR_LOCATION_31 = TMP_DIR
+ + "CtsAppThatRequestsBluetoothPermissionNeverForLocation31.apk";
+ private static final String APK_BLUETOOTH_NEVER_FOR_LOCATION_NO_PROVIDER = TMP_DIR
+ + "CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider.apk";
+
+ private enum Result {
+ UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
+ }
+
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+ @ClassRule
+ public static final EnableBluetoothRule sEnableBluetoothRule = new EnableBluetoothRule(true);
+
+ @Rule
+ public final EnableLocationRule enableLocationRule = new EnableLocationRule();
+
+ public void uninstallTestApp() {
+ uninstallApp(TEST_APP_PKG);
+ uninstallApp(DISAVOWAL_APP_PKG);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallTestApp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ uninstallTestApp();
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission30_Default() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_30);
+ assertScanBluetoothResult(Result.EMPTY);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission30_GrantLocation() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_30);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.FULL);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission31_Default() throws Throwable {
+ install(APK_BLUETOOTH_31);
+ assertScanBluetoothResult(Result.EXCEPTION);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission31_GrantNearby() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_31);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ assertScanBluetoothResult(Result.EMPTY);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission31_GrantLocation() throws Throwable {
+ install(APK_BLUETOOTH_31);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.EXCEPTION);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermission31_GrantNearby_GrantLocation() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_31);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.FULL);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermissionNeverForLocation31_Default() throws Throwable {
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
+ assertScanBluetoothResult(Result.EXCEPTION);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermissionNeverForLocation31_GrantNearby() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ assertScanBluetoothResult(Result.FILTERED);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermissionNeverForLocation31_GrantLocation() throws Throwable {
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.EXCEPTION);
+ }
+
+ @Test
+ @CddTest(requirement = "7.4.3/C-6-1")
+ public void testRequestBluetoothPermissionNeverForLocation31_GrantNearby_GrantLocation()
+ throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.FILTERED);
+ }
+
+ @Test
+ public void testRequestBluetoothPermission31_OnBehalfOfDisavowingApp() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_31);
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_NO_PROVIDER);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ grantPermission(DISAVOWAL_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(DISAVOWAL_APP_PKG, BLUETOOTH_SCAN);
+ assertScanBluetoothResult("PROXY", Result.FILTERED);
+ }
+
+ /**
+ * Verify that a legacy app that was unable to interact with Bluetooth
+ * devices is still unable to interact with them after updating to a modern
+ * SDK; they'd always need to involve the user to gain permissions.
+ */
+ @Test
+ public void testRequestBluetoothPermission_Default_Upgrade() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_30);
+ assertScanBluetoothResult(Result.EMPTY);
+
+ // Upgrading to target a new SDK level means they need to explicitly
+ // request the new runtime permission; by default it's denied
+ install(APK_BLUETOOTH_NEVER_FOR_LOCATION_31);
+ assertScanBluetoothResult(Result.EXCEPTION);
+
+ // If the user does grant it, they can scan again
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ assertScanBluetoothResult(Result.FILTERED);
+ }
+
+ /**
+ * Verify that a legacy app that was able to interact with Bluetooth devices
+ * is still able to interact with them after updating to a modern SDK.
+ */
+ @Test
+ public void testRequestBluetoothPermission_GrantLocation_Upgrade() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_30);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.FULL);
+
+ // Upgrading to target a new SDK level means they still have the access
+ // they enjoyed as a legacy app
+ install(APK_BLUETOOTH_31);
+ assertScanBluetoothResult(Result.FULL);
+ }
+
+ /**
+ * Verify that downgrading an app doesn't gain them any access to Bluetooth
+ * scan results; they'd always need to involve the user to gain permissions.
+ */
+ @Test
+ public void testRequestBluetoothPermission_Downgrade() throws Throwable {
+ assumeTrue(supportsBluetoothLe());
+
+ install(APK_BLUETOOTH_31);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ grantPermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ grantPermission(TEST_APP_PKG, ACCESS_FINE_LOCATION);
+ grantPermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ assertScanBluetoothResult(Result.FULL);
+
+ // Revoking nearby permission means modern app can't scan
+ revokePermission(TEST_APP_PKG, BLUETOOTH_CONNECT);
+ revokePermission(TEST_APP_PKG, BLUETOOTH_SCAN);
+ assertScanBluetoothResult(Result.EXCEPTION);
+
+ // And if they attempt to downgrade, confirm that they can't obtain the
+ // split-permission grant from the older non-runtime permissions
+ install(APK_BLUETOOTH_30);
+ assertScanBluetoothResult(Result.EXCEPTION);
+ }
+
+ private void assertScanBluetoothResult(Result expected) {
+ assertScanBluetoothResult(null, expected);
+ }
+
+ private void assertScanBluetoothResult(String arg, Result expected) {
+ SystemClock.sleep(1000); // Wait for location permissions to propagate
+ final ContentResolver resolver = InstrumentationRegistry.getTargetContext()
+ .getContentResolver();
+ final Bundle res = resolver.call(TEST_APP_AUTHORITY, "", arg, null);
+ Result actual = Result.values()[res.getInt(Intent.EXTRA_INDEX)];
+ assertEquals(expected, actual);
+ }
+
+ private boolean supportsBluetoothLe() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
+ }
+
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
new file mode 100644
index 000000000..a196cedfd
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NearbyDevicesRenouncePermissionTest.java
@@ -0,0 +1,275 @@
+/*
+ * 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.app.AppOpsManager;
+import android.app.AsyncNotedAppOp;
+import android.app.SyncNotedAppOp;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.cts.EnableBluetoothRule;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanResult;
+import android.content.AttributionSource;
+import android.content.Context;
+import android.content.ContextParams;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
+import android.util.ArraySet;
+import android.util.Base64;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.EnableLocationRule;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Tests behaviour when performing bluetooth scans with renounced location permission.
+ */
+public class NearbyDevicesRenouncePermissionTest {
+
+ private static final String TAG = "NearbyDevicesRenouncePermissionTest";
+ private static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
+
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+ @ClassRule
+ public static final EnableBluetoothRule sEnableBluetoothRule = new EnableBluetoothRule(true);
+
+ @Rule
+ public final EnableLocationRule enableLocationRule = new EnableLocationRule();
+
+ private AppOpsManager mAppOpsManager;
+ private int mLocationNoteCount;
+ private int mScanNoteCount;
+
+ private enum Result {
+ UNKNOWN, EXCEPTION, EMPTY, FILTERED, FULL
+ }
+
+ private enum Scenario {
+ DEFAULT, RENOUNCE, RENOUNCE_MIDDLE, RENOUNCE_END
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mAppOpsManager = getApplicationContext().getSystemService(AppOpsManager.class);
+ mAppOpsManager.setOnOpNotedCallback(getApplicationContext().getMainExecutor(),
+ new AppOpsManager.OnOpNotedCallback() {
+ @Override
+ public void onNoted(SyncNotedAppOp op) {
+ switch (op.getOp()) {
+ case OPSTR_FINE_LOCATION:
+ mLocationNoteCount++;
+ break;
+ case OPSTR_BLUETOOTH_SCAN:
+ mScanNoteCount++;
+ break;
+ default:
+ }
+ }
+
+ @Override
+ public void onSelfNoted(SyncNotedAppOp op) {
+ }
+
+ @Override
+ public void onAsyncNoted(AsyncNotedAppOp asyncOp) {
+ switch (asyncOp.getOp()) {
+ case OPSTR_FINE_LOCATION:
+ mLocationNoteCount++;
+ break;
+ case OPSTR_BLUETOOTH_SCAN:
+ mScanNoteCount++;
+ break;
+ default:
+ }
+ }
+ });
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mAppOpsManager.setOnOpNotedCallback(null, null);
+ }
+
+ private void clearNoteCounts() {
+ mLocationNoteCount = 0;
+ mScanNoteCount = 0;
+ }
+
+ @AppModeFull
+ @Test
+ public void scanWithoutRenouncingNotesBluetoothAndLocation() throws Exception {
+ assumeTrue(supportsBluetoothLe());
+
+ clearNoteCounts();
+ assertThat(performScan(Scenario.DEFAULT)).isEqualTo(Result.FULL);
+ SystemUtil.eventually(() -> {
+ assertThat(mLocationNoteCount).isGreaterThan(0);
+ assertThat(mScanNoteCount).isGreaterThan(0);
+ });
+ }
+
+ @AppModeFull
+ @Test
+ public void scanRenouncingLocationNotesBluetoothButNotLocation() throws Exception {
+ assumeTrue(supportsBluetoothLe());
+
+ clearNoteCounts();
+ assertThat(performScan(Scenario.RENOUNCE)).isEqualTo(Result.FILTERED);
+ SystemUtil.eventually(() -> {
+ assertThat(mLocationNoteCount).isEqualTo(0);
+ assertThat(mScanNoteCount).isGreaterThan(0);
+ });
+ }
+
+ @AppModeFull
+ @Test
+ public void scanRenouncingInMiddleOfChainNotesBluetoothButNotLocation() throws Exception {
+ assumeTrue(supportsBluetoothLe());
+
+ clearNoteCounts();
+ assertThat(performScan(Scenario.RENOUNCE_MIDDLE)).isEqualTo(Result.FILTERED);
+ SystemUtil.eventually(() -> {
+ assertThat(mLocationNoteCount).isEqualTo(0);
+ assertThat(mScanNoteCount).isGreaterThan(0);
+ });
+ }
+
+ @AppModeFull
+ @Test
+ public void scanRenouncingAtEndOfChainNotesBluetoothButNotLocation() throws Exception {
+ clearNoteCounts();
+ assertThat(performScan(Scenario.RENOUNCE_END)).isEqualTo(Result.FILTERED);
+ SystemUtil.eventually(() -> {
+ assertThat(mLocationNoteCount).isEqualTo(0);
+ assertThat(mScanNoteCount).isGreaterThan(0);
+ });
+ }
+
+ private Result performScan(Scenario scenario) {
+ try {
+ Context context = createContext(scenario, getApplicationContext());
+
+ final BluetoothManager bm = context.getSystemService(BluetoothManager.class);
+ final BluetoothLeScanner scanner = bm.getAdapter().getBluetoothLeScanner();
+
+ final HashSet<String> observed = new HashSet<>();
+
+ ScanCallback callback = new ScanCallback() {
+ public void onScanResult(int callbackType, ScanResult result) {
+ Log.v(TAG, String.valueOf(result));
+ observed.add(Base64.encodeToString(result.getScanRecord().getBytes(), 0));
+ }
+
+ public void onBatchScanResults(List<ScanResult> results) {
+ for (ScanResult result : results) {
+ onScanResult(0, result);
+ }
+ }
+ };
+ scanner.startScan(callback);
+
+ // Wait a few seconds to figure out what we actually observed
+ SystemClock.sleep(3000);
+ scanner.stopScan(callback);
+ switch (observed.size()) {
+ case 0:
+ return Result.EMPTY;
+ case 1:
+ return Result.FILTERED;
+ case 5:
+ return Result.FULL;
+ default:
+ return Result.UNKNOWN;
+ }
+ } catch (Throwable t) {
+ Log.v(TAG, "Failed to scan", t);
+ return Result.EXCEPTION;
+ }
+ }
+
+ private Context createContext(Scenario scenario, Context context) throws Exception {
+ if (scenario == Scenario.DEFAULT) {
+ return context;
+ }
+
+ Set<String> renouncedPermissions = new ArraySet<>();
+ renouncedPermissions.add(ACCESS_FINE_LOCATION);
+
+ switch (scenario) {
+ case RENOUNCE:
+ return SystemUtil.callWithShellPermissionIdentity(() ->
+ context.createContext(
+ new ContextParams.Builder()
+ .setRenouncedPermissions(renouncedPermissions)
+ .setAttributionTag(context.getAttributionTag())
+ .build())
+ );
+ case RENOUNCE_MIDDLE:
+ AttributionSource nextAttrib = new AttributionSource(
+ Process.SHELL_UID, "com.android.shell", null, (Set<String>) null, null);
+ return SystemUtil.callWithShellPermissionIdentity(() ->
+ context.createContext(
+ new ContextParams.Builder()
+ .setRenouncedPermissions(renouncedPermissions)
+ .setAttributionTag(context.getAttributionTag())
+ .setNextAttributionSource(nextAttrib)
+ .build())
+ );
+ case RENOUNCE_END:
+ nextAttrib = new AttributionSource(
+ Process.SHELL_UID, "com.android.shell", null, renouncedPermissions, null);
+ return SystemUtil.callWithShellPermissionIdentity(() ->
+ context.createContext(
+ new ContextParams.Builder()
+ .setAttributionTag(context.getAttributionTag())
+ .setNextAttributionSource(nextAttrib)
+ .build())
+ );
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private boolean supportsBluetoothLe() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NfcPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NfcPermissionTest.java
new file mode 100644
index 000000000..1b3f65ee6
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NfcPermissionTest.java
@@ -0,0 +1,221 @@
+/*
+ * 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.permission.cts;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.ActivityManager;
+import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.concurrent.Executor;
+
+@RunWith(JUnit4.class)
+public final class NfcPermissionTest {
+
+ private NfcAdapter mNfcAdapter;
+ private static final String PKG_NAME = "com.android.packagename";
+
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
+ }
+
+ @Before
+ public void setUp() {
+ assumeTrue(supportsHardware());
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(InstrumentationRegistry.getTargetContext());
+ }
+
+ /**
+ * Verifies that isControllerAlwaysOnSupported() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testIsControllerAlwaysOnSupported() {
+ try {
+ mNfcAdapter.isControllerAlwaysOnSupported();
+ fail("mNfcAdapter.isControllerAlwaysOnSupported() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that isControllerAlwaysOn() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testIsControllerAlwaysOn() {
+ try {
+ mNfcAdapter.isControllerAlwaysOn();
+ fail("mNfcAdapter.isControllerAlwaysOn() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that setControllerAlwaysOn(true) requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testSetControllerAlwaysOnTrue() {
+ try {
+ mNfcAdapter.setControllerAlwaysOn(true);
+ fail("mNfcAdapter.setControllerAlwaysOn(true) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that setControllerAlwaysOn(false) requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testSetControllerAlwaysOnFalse() {
+ try {
+ mNfcAdapter.setControllerAlwaysOn(false);
+ fail("mNfcAdapter.setControllerAlwaysOn(true) did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that registerControllerAlwaysOnListener() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testRegisterControllerAlwaysOnListener() {
+ try {
+ mNfcAdapter.registerControllerAlwaysOnListener(
+ new SynchronousExecutor(), new AlwaysOnStateListener());
+ fail("mNfcAdapter.registerControllerAlwaysOnListener did not throw"
+ + "SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that unregisterControllerAlwaysOnListener() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON}.
+ */
+ @Test
+ @AppModeFull
+ public void testUnregisterControllerAlwaysOnListener() {
+ try {
+ mNfcAdapter.unregisterControllerAlwaysOnListener(new AlwaysOnStateListener());
+ fail("mNfcAdapter.unregisterControllerAlwaysOnListener did not throw"
+ + "SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that isTagIntentAppPreferenceSupported() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testIsTagIntentAppPreferenceSupported() {
+ try {
+ mNfcAdapter.isTagIntentAppPreferenceSupported();
+ fail("mNfcAdapter.isTagIntentAppPreferenceSupported() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that getTagIntentAppPreferenceForUser() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testGetTagIntentAppPreferenceForUser() {
+ try {
+ mNfcAdapter.getTagIntentAppPreferenceForUser(ActivityManager.getCurrentUser());
+ fail("mNfcAdapter.getTagIntentAppPreferenceForUser() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that setTagIntentAppPreferenceForUser() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testSetTagIntentAppPreferenceForUser() {
+ try {
+ mNfcAdapter.setTagIntentAppPreferenceForUser(ActivityManager.getCurrentUser(),
+ PKG_NAME, true);
+ fail("mNfcAdapter.setTagIntentAppPreferenceForUser() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ private class SynchronousExecutor implements Executor {
+ public void execute(Runnable r) {
+ r.run();
+ }
+ }
+
+ private class AlwaysOnStateListener implements ControllerAlwaysOnListener {
+ @Override
+ public void onControllerAlwaysOnChanged(boolean isEnabled) {
+ // Do nothing
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
new file mode 100644
index 000000000..835ba124c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.util.List;
+
+/**
+ * Verify the Activity related operations require specific permissions.
+ */
+public class NoActivityRelatedPermissionTest
+ extends ActivityInstrumentationTestCase2<PermissionStubActivity> {
+
+ private PermissionStubActivity mActivity;
+
+ public NoActivityRelatedPermissionTest() {
+ super("android.permission.cts", PermissionStubActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ }
+
+ /**
+ * Verify that get task requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#GET_TASKS}
+ */
+ @MediumTest
+ public void testGetTask() {
+ ActivityManager manager = (ActivityManager) getActivity()
+ .getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RunningTaskInfo> runningTasks = manager.getRunningTasks(10);
+ // Current implementation should only return tasks for home and the caller. Since there can
+ // be multiple home tasks, we remove them from the list and then check that there is one or
+ // less task left in the list.
+ removeHomeRunningTasks(runningTasks);
+ assertTrue("Found tasks: " + runningTasks,
+ runningTasks == null || runningTasks.size() <= 1);
+
+ List<ActivityManager.RecentTaskInfo> recentTasks = manager.getRecentTasks(10,
+ ActivityManager.RECENT_WITH_EXCLUDED);
+ // Current implementation should only return tasks for home and the caller. Since there can
+ // be multiple home tasks, we remove them from the list and then check that there is one or
+ // less task left in the list.
+ removeHomeRecentsTasks(recentTasks);
+ assertTrue("Found tasks: " + recentTasks, recentTasks == null || recentTasks.size() <= 1);
+ }
+
+ private void removeHomeRecentsTasks(List<ActivityManager.RecentTaskInfo> tasks) {
+ for (int i = tasks.size() -1; i >= 0; i--) {
+ ActivityManager.RecentTaskInfo task = tasks.get(i);
+ if (task.baseIntent != null && isHomeIntent(task.baseIntent)) {
+ tasks.remove(i);
+ }
+ }
+ }
+
+ private void removeHomeRunningTasks(List<ActivityManager.RunningTaskInfo> tasks) {
+ for (int i = tasks.size() -1; i >= 0; i--) {
+ ActivityManager.RunningTaskInfo task = tasks.get(i);
+ if (task.baseIntent != null && isHomeIntent(task.baseIntent)) {
+ tasks.remove(i);
+ }
+ }
+ }
+
+ private boolean isHomeIntent(Intent intent) {
+ return Intent.ACTION_MAIN.equals(intent.getAction())
+ && (intent.hasCategory(Intent.CATEGORY_HOME)
+ || intent.hasCategory(Intent.CATEGORY_SECONDARY_HOME))
+ && intent.getCategories().size() == 1
+ && intent.getData() == null
+ && intent.getType() == null;
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java
new file mode 100644
index 000000000..c2c42a10d
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoAudioPermissionTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+/**
+ * Verify the audio related operations require specific permissions.
+ */
+public class NoAudioPermissionTest extends AndroidTestCase {
+ private static final String TAG = NoAudioPermissionTest.class.getSimpleName();
+ private AudioManager mAudioManager;
+ private static final int MODE_COUNT = 3;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ assertNotNull(mAudioManager);
+ }
+
+ private boolean hasMicrophone() {
+ return getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_MICROPHONE);
+ }
+
+ /**
+ * Verify that AudioManager.setMicrophoneMute, AudioManager.setMode requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+ */
+ @SmallTest
+ public void testSetMicrophoneMute() {
+ boolean muteState = mAudioManager.isMicrophoneMute();
+ int originalMode = mAudioManager.getMode();
+ // If there is no permission of MODIFY_AUDIO_SETTINGS, setMicrophoneMute does nothing.
+ if (muteState) {
+ Log.w(TAG, "Mic seems muted by hardware! Please unmute and rerrun the test.");
+ } else {
+ mAudioManager.setMicrophoneMute(!muteState);
+ assertEquals(muteState, mAudioManager.isMicrophoneMute());
+ }
+
+ // If there is no permission of MODIFY_AUDIO_SETTINGS, setMode does nothing.
+ assertTrue(AudioManager.MODE_NORMAL != AudioManager.MODE_RINGTONE);
+
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ assertEquals(originalMode, mAudioManager.getMode());
+
+ mAudioManager.setMode(AudioManager.MODE_RINGTONE);
+ assertEquals(originalMode, mAudioManager.getMode());
+ }
+
+ /**
+ * Verify that AudioManager routing methods require permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
+ */
+ @SuppressWarnings("deprecation")
+ @SmallTest
+ public void testRouting() {
+
+ // If there is no permission of MODIFY_AUDIO_SETTINGS, setSpeakerphoneOn does nothing.
+ boolean prevState = mAudioManager.isSpeakerphoneOn();
+ mAudioManager.setSpeakerphoneOn(!prevState);
+ assertEquals(prevState, mAudioManager.isSpeakerphoneOn());
+
+ // If there is no permission of MODIFY_AUDIO_SETTINGS, setBluetoothScoOn does nothing.
+ prevState = mAudioManager.isBluetoothScoOn();
+ mAudioManager.setBluetoothScoOn(!prevState);
+ assertEquals(prevState, mAudioManager.isBluetoothScoOn());
+ }
+
+ /**
+ * Verify that {@link android.media.AudioRecord.Builder#build} and
+ * {@link android.media.AudioRecord#AudioRecord} require permission
+ * {@link android.Manifest.permission#RECORD_AUDIO}.
+ */
+ @SmallTest
+ public void testRecordPermission() {
+ if (!hasMicrophone()) return;
+
+ // test builder
+ assertThrows(java.lang.UnsupportedOperationException.class, () -> {
+ final AudioRecord record = new AudioRecord.Builder().build();
+ record.release();
+ });
+
+ // test constructor
+ final int sampleRate = 8000;
+ final int halfSecondInBytes = sampleRate;
+ AudioRecord record = new AudioRecord(
+ MediaRecorder.AudioSource.DEFAULT, sampleRate, AudioFormat.CHANNEL_IN_MONO,
+ AudioFormat.ENCODING_PCM_16BIT, halfSecondInBytes);
+ final int state = record.getState();
+ record.release();
+ assertEquals(AudioRecord.STATE_UNINITIALIZED, state);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java
new file mode 100644
index 000000000..5630c5b8c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoBroadcastPackageRemovedPermissionTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify Context related methods without specific BROADCAST series permissions.
+ */
+public class NoBroadcastPackageRemovedPermissionTest extends AndroidTestCase {
+ private static final String TEST_RECEIVER_PERMISSION = "receiverPermission";
+
+ /**
+ * Verify that Context#sendStickyBroadcast(Intent),
+ * Context#removeStickyBroadcast(Intent)
+ * requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#BROADCAST_STICKY }.
+ */
+ @SmallTest
+ public void testSendOrRemoveStickyBroadcast() {
+ try {
+ mContext.sendStickyBroadcast(createIntent(Intent.ACTION_WALLPAPER_CHANGED));
+ fail("Context.sendStickyBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.removeStickyBroadcast(createIntent(Intent.ACTION_WALLPAPER_CHANGED));
+ fail("Context.removeStickyBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that Context#sendBroadcast(Intent),
+ * Context#sendBroadcast(Intent, String)
+ * Context#sendOrderedBroadcast(Intent, String, BroadcastReceiver,
+ * Handler, int, String, Bundle)
+ * Context#sendOrderedBroadcast(Intent, String) with ACTION_UID_REMOVED
+ * with ACTION_PACKAGE_REMOVED requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#BROADCAST_PACKAGE_REMOVED}.
+ */
+ @SmallTest
+ public void testSendBroadcast() {
+ try {
+ mContext.sendBroadcast(createIntent(Intent.ACTION_PACKAGE_REMOVED));
+ fail("Context.sendBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.sendBroadcast(createIntent(Intent.ACTION_PACKAGE_REMOVED),
+ TEST_RECEIVER_PERMISSION);
+ fail("Context.sendBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.sendOrderedBroadcast(createIntent(Intent.ACTION_PACKAGE_REMOVED),
+ TEST_RECEIVER_PERMISSION, null, null, 0, "initialData", Bundle.EMPTY);
+ fail("Context.sendOrderedBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.sendOrderedBroadcast(createIntent(Intent.ACTION_PACKAGE_REMOVED),
+ TEST_RECEIVER_PERMISSION);
+ fail("Context.sendOrderedBroadcast did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ private Intent createIntent(String action) {
+ Intent intent = new Intent();
+ intent.setAction(action);
+ return intent;
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java
new file mode 100644
index 000000000..6ad048308
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoCaptureVideoPermissionTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013 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.permission.cts;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.media.ImageReader;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.DisplayMetrics;
+
+/**
+ * Verify the capture system video output permission requirements.
+ */
+public class NoCaptureVideoPermissionTest extends AndroidTestCase {
+ private static final String NAME = "VirtualDisplayTest";
+ private static final int WIDTH = 720;
+ private static final int HEIGHT = 480;
+ private static final int DENSITY = DisplayMetrics.DENSITY_MEDIUM;
+
+ /**
+ * Verify that DisplayManager.createVirtualDisplay() requires permissions to
+ * create public displays.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT} or
+ * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT}.
+ */
+ @SmallTest
+ public void testCreatePublicVirtualDisplay() {
+ DisplayManager displayManager =
+ (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
+ ImageReader reader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBX_8888, 1);
+ try {
+ displayManager.createVirtualDisplay(NAME, WIDTH, HEIGHT, DENSITY,
+ reader.getSurface(), DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC);
+ fail("DisplayManager.createVirtualDisplay() didn't throw SecurityException "
+ + "as expected when creating public virtual display.");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Verify that DisplayManager.createVirtualDisplay() requires permissions to
+ * create secure displays.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT}.
+ */
+ @SmallTest
+ public void testCreateSecureVirtualDisplay() {
+ DisplayManager displayManager =
+ (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
+ ImageReader reader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBX_8888, 1);
+ try {
+ displayManager.createVirtualDisplay(NAME, WIDTH, HEIGHT, DENSITY,
+ reader.getSurface(), DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE);
+ fail("DisplayManager.createVirtualDisplay() didn't throw SecurityException "
+ + "as expected when creating secure virtual display.");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Verify that DisplayManager.createVirtualDisplay() does not requires permissions to
+ * create private displays.
+ */
+ @SmallTest
+ public void testCreatePrivateVirtualDisplay() {
+ DisplayManager displayManager =
+ (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
+ ImageReader reader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBX_8888, 1);
+ try {
+ VirtualDisplay display = displayManager.createVirtualDisplay(
+ NAME, WIDTH, HEIGHT, DENSITY,
+ reader.getSurface(), 0);
+ display.release();
+ } catch (SecurityException e) {
+ fail("DisplayManager.createVirtualDisplay() should not throw SecurityException "
+ + "when creating private virtual display.");
+ } finally {
+ reader.close();
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java
new file mode 100644
index 000000000..5a0b25993
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoKeyPermissionTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify the key input related operations require specific permissions.
+ */
+public class NoKeyPermissionTest extends AndroidTestCase {
+ KeyguardManager mKeyManager;
+ KeyguardManager.KeyguardLock mKeyLock;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mKeyManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ if (mKeyManager != null) {
+ mKeyLock = mKeyManager.newKeyguardLock("testTag");
+ }
+ }
+
+ /**
+ * Verify that KeyguardManager.KeyguardLock.disableKeyguard requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
+ */
+ @SmallTest
+ public void testDisableKeyguard() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
+ try {
+ mKeyLock.disableKeyguard();
+ fail("KeyguardManager.KeyguardLock.disableKeyguard did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that KeyguardManager.KeyguardLock.reenableKeyguard requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
+ */
+ @SmallTest
+ public void testReenableKeyguard() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
+ try {
+ mKeyLock.reenableKeyguard();
+ fail("KeyguardManager.KeyguardLock.reenableKeyguard did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that KeyguardManager.exitKeyguardSecurely requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#DISABLE_KEYGUARD}.
+ */
+ @SmallTest
+ public void testExitKeyguardSecurely() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
+ try {
+ mKeyManager.exitKeyguardSecurely(null);
+ fail("KeyguardManager.exitKeyguardSecurely did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
new file mode 100644
index 000000000..b8d2ee21a
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.net.InetAddress;
+
+/**
+ * Verify ConnectivityManager related methods without specific network state permissions.
+ */
+public class NoNetworkStatePermissionTest extends AndroidTestCase {
+ private ConnectivityManager mConnectivityManager;
+ private static final int TEST_NETWORK_TYPE = ConnectivityManager.TYPE_MOBILE;
+ private static final String TEST_FEATURE = "enableHIPRI";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ assertNotNull(mConnectivityManager);
+ }
+
+ /**
+ * Verify that ConnectivityManager#getActiveNetworkInfo() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ */
+ @SmallTest
+ public void testGetActiveNetworkInfo() {
+ try {
+ mConnectivityManager.getActiveNetworkInfo();
+ fail("ConnectivityManager.getActiveNetworkInfo didn't throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that ConnectivityManager#getNetworkInfo() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ */
+ @SmallTest
+ public void testGetNetworkInfo() {
+ try {
+ mConnectivityManager.getNetworkInfo(TEST_NETWORK_TYPE);
+ fail("ConnectivityManager.getNetworkInfo didn't throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that ConnectivityManager#getAllNetworkInfo() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ */
+ @SmallTest
+ public void testGetAllNetworkInfo() {
+ try {
+ mConnectivityManager.getAllNetworkInfo();
+ fail("ConnectivityManager.getAllNetworkInfo didn't throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testSecurityExceptionFromDns() throws Exception {
+ try {
+ InetAddress.getByName("www.google.com");
+ fail();
+ } catch (SecurityException expected) {
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
new file mode 100644
index 000000000..b6fb84dc7
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Verify the read system log require specific permissions.
+ */
+public class NoReadLogsPermissionTest extends AndroidTestCase {
+ /**
+ * Verify that we'll only get our logs without the READ_LOGS permission.
+ *
+ * We test this by examining the logs looking for ActivityManager lines.
+ * Since ActivityManager runs as a different UID, we shouldn't see
+ * any of those log entries.
+ *
+ * @throws IOException
+ */
+ @MediumTest
+ public void testLogcat() throws IOException {
+ Process logcatProc = null;
+ BufferedReader reader = null;
+ try {
+ logcatProc = Runtime.getRuntime().exec(new String[]
+ {"logcat", "-v", "brief", "-d", "ActivityManager:* *:S" });
+
+ reader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()));
+
+ int lineCt = 0;
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (!line.startsWith("--------- beginning of ")) {
+ lineCt++;
+ }
+ }
+
+ // no permission get an empty log buffer.
+ // Logcat returns only one line:
+ // "--------- beginning of <log device>"
+
+ assertEquals("Unexpected logcat entries. Are you running the "
+ + "the latest logger.c from the Android kernel?",
+ 0, lineCt);
+
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+
+ public void testEventsLogSane() throws ErrnoException {
+ testLogIsSane("/dev/log/events");
+ }
+
+ public void testMainLogSane() throws ErrnoException {
+ testLogIsSane("/dev/log/main");
+ }
+
+ public void testRadioLogSane() throws ErrnoException {
+ testLogIsSane("/dev/log/radio");
+ }
+
+ public void testSystemLogSane() throws ErrnoException {
+ testLogIsSane("/dev/log/system");
+ }
+
+ private static void testLogIsSane(String log) throws ErrnoException {
+ try {
+ StructStat stat = Os.stat(log);
+ assertEquals("not owned by uid=0", 0, stat.st_uid);
+ assertEquals("not owned by gid=logs", "log", FileUtils.getGroupName(stat.st_gid));
+ } catch (ErrnoException e) {
+ if (e.errno != OsConstants.ENOENT && e.errno != OsConstants.EACCES) {
+ throw e;
+ }
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoRollbackPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoRollbackPermissionTest.java
new file mode 100644
index 000000000..50b84fa70
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoRollbackPermissionTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.pm.PackageInstaller;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+
+@AppModeFull(reason = "PackageInstaller cannot be accessed by instant apps")
+public class NoRollbackPermissionTest {
+ @Test
+ public void testCreateInstallSessionWithReasonRollbackFails() throws Exception {
+ // The INSTALL_REASON_ROLLBACK allows an APK to be rolled back to a previous signing key
+ // without setting the ROLLBACK capability in the lineage. Since only signature|privileged
+ // apps can hold the necessary permission to initiate a rollback ensure apps without this
+ // permission cannot set rollback as the install reason.
+ PackageInstaller packageInstaller =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager()
+ .getPackageInstaller();
+ PackageInstaller.SessionParams parentParams = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ parentParams.setRequestDowngrade(true);
+ parentParams.setMultiPackage();
+ // The constant PackageManager.INSTALL_REASON_ROLLBACK is hidden from apps, but an app can
+ // still use its constant value.
+ parentParams.setInstallReason(5);
+ assertThrows(SecurityException.class, () -> packageInstaller.createSession(parentParams));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
new file mode 100644
index 000000000..0ccebed04
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.os.Vibrator;
+import android.platform.test.annotations.AppModeFull;
+import android.telephony.gsm.SmsManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.TimeZone;
+
+/**
+ * Verify the system function require specific permissions.
+ */
+@SuppressWarnings("deprecation")
+public class NoSystemFunctionPermissionTest extends AndroidTestCase {
+
+ /**
+ * Verify that ActivityManager.restartPackage() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#RESTART_PACKAGES}.
+ */
+ @SmallTest
+ public void testRestartPackage() {
+ ActivityManager activityManager = (ActivityManager) mContext.getSystemService(
+ Context.ACTIVITY_SERVICE);
+
+ try {
+ activityManager.restartPackage("packageName");
+ fail("ActivityManager.restartPackage() didn't throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that AlarmManager.setTimeZone() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#SET_TIME_ZONE}.
+ */
+ @SmallTest
+ public void testSetTimeZone() {
+ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(
+ Context.ALARM_SERVICE);
+ String[] timeZones = TimeZone.getAvailableIDs();
+ String timeZone = timeZones[0];
+
+ try {
+ alarmManager.setTimeZone(timeZone);
+ fail("AlarmManager.setTimeZone() did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that setting wallpaper relate methods require permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#SET_WALLPAPER}.
+ * @throws IOException
+ */
+ @AppModeFull(reason = "Instant apps cannot access the WallpaperManager")
+ @SmallTest
+ public void testSetWallpaper() throws IOException {
+ if (!WallpaperManager.getInstance(mContext).isWallpaperSupported()) {
+ return;
+ }
+
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
+
+ try {
+ mContext.setWallpaper(bitmap);
+ fail("Context.setWallpaper(BitMap) did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.setWallpaper((InputStream) null);
+ fail("Context.setWallpaper(InputStream) did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mContext.clearWallpaper();
+ fail("Context.clearWallpaper() did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that Vibrator's vibrating related methods requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#VIBRATE}.
+ */
+ @SmallTest
+ public void testVibrator() {
+ Vibrator vibrator = (Vibrator)getContext().getSystemService(Context.VIBRATOR_SERVICE);
+
+ try {
+ vibrator.cancel();
+ fail("Vibrator.cancel() did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ vibrator.vibrate(1);
+ fail("Vibrator.vibrate(long) did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ long[] testPattern = {1, 1, 1, 1, 1};
+
+ try {
+ vibrator.vibrate(testPattern, 1);
+ fail("Vibrator.vibrate(long[], int) not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that sending sms requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#SMS}.
+ */
+ @SmallTest
+ public void testSendSms() {
+ if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ SmsManager smsManager = SmsManager.getDefault();
+ byte[] testData = new byte[10];
+ try {
+ smsManager.sendDataMessage("1233", "1233", (short) 0, testData, null, null);
+ fail("SmsManager.sendDataMessage() did not throw SecurityException as expected.");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
new file mode 100644
index 000000000..030f341aa
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.PowerManager;
+import android.platform.test.annotations.AppModeFull;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify the Wake Lock related operations require specific permissions.
+ */
+public class NoWakeLockPermissionTest extends AndroidTestCase {
+ private PowerManager mPowerManager;
+
+ private PowerManager.WakeLock mWakeLock;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "tag");
+ }
+
+ /**
+ * Verify that WifiManager.WifiLock.acquire() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#WAKE_LOCK}.
+ */
+ @AppModeFull(reason = "Instant apps cannot access the WifiManager")
+ @SmallTest
+ public void testWifiLockAcquire() {
+ if (!mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI)) {
+ return;
+ }
+
+ final WifiManager wifiManager = (WifiManager) mContext.getSystemService(
+ Context.WIFI_SERVICE);
+ final WifiLock wifiLock = wifiManager.createWifiLock("WakeLockPermissionTest");
+ try {
+ wifiLock.acquire();
+ fail("WifiManager.WifiLock.acquire() didn't throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that MediaPlayer.start() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#WAKE_LOCK}.
+ */
+ @SmallTest
+ public void testMediaPlayerWakeLock() {
+ final MediaPlayer mediaPlayer = new MediaPlayer();
+ mediaPlayer.setWakeMode(mContext, PowerManager.FULL_WAKE_LOCK);
+ try {
+ mediaPlayer.start();
+ fail("MediaPlayer.setWakeMode() did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ mediaPlayer.stop();
+ }
+
+ /**
+ * Verify that PowerManager.WakeLock.acquire() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#WAKE_LOCK}.
+ */
+ @SmallTest
+ public void testPowerManagerWakeLockAcquire() {
+ try {
+ mWakeLock.acquire();
+ fail("WakeLock.acquire() did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that PowerManager.WakeLock.acquire(long) requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#WAKE_LOCK}.
+ */
+ @SmallTest
+ public void testPowerManagerWakeLockAcquire2() {
+ // Tset acquire(long)
+ try {
+ mWakeLock.acquire(1);
+ fail("WakeLock.acquire(long) did not throw SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
new file mode 100644
index 000000000..18e4375bc
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2017 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.permission.cts;
+
+import static android.app.WallpaperManager.FLAG_LOCK;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.platform.test.annotations.AppModeFull;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.function.ThrowingRunnable;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+/**
+ * Verify that Wallpaper-related operations enforce the correct permissions.
+ */
+@AppModeFull(reason = "instant apps cannot access the WallpaperManager")
+public class NoWallpaperPermissionsTest extends AndroidTestCase {
+ private WallpaperManager mWM;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mWM = (WallpaperManager) mContext.getSystemService(Context.WALLPAPER_SERVICE);
+ }
+
+ /**
+ * Verify that the setResource(...) methods enforce the SET_WALLPAPER permission
+ */
+ @SmallTest
+ public void testSetResource() throws IOException {
+ if (wallpaperNotSupported()) {
+ return;
+ }
+
+ try {
+ mWM.setResource(R.drawable.robot);
+ fail("WallpaperManager.setResource(id) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.setResource(R.drawable.robot, FLAG_LOCK);
+ fail("WallpaperManager.setResource(id, which) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+ }
+
+ /**
+ * Verify that the setBitmap(...) methods enforce the SET_WALLPAPER permission
+ */
+ @SmallTest
+ public void testSetBitmap() throws IOException {
+ if (wallpaperNotSupported()) {
+ return;
+ }
+
+ Bitmap b = Bitmap.createBitmap(160, 120, Bitmap.Config.RGB_565);
+
+ try {
+ mWM.setBitmap(b);
+ fail("setBitmap(b) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.setBitmap(b, null, false);
+ fail("setBitmap(b, crop, allowBackup) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.setBitmap(b, null, false, FLAG_SYSTEM);
+ fail("setBitmap(b, crop, allowBackup, which) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+ }
+
+ /**
+ * Verify that the setStream(...) methods enforce the SET_WALLPAPER permission
+ */
+ @SmallTest
+ public void testSetStream() throws IOException {
+ if (wallpaperNotSupported()) {
+ return;
+ }
+
+ ByteArrayInputStream stream = new ByteArrayInputStream(new byte[32]);
+
+ try {
+ mWM.setStream(stream);
+ fail("setStream(stream) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.setStream(stream, null, false);
+ fail("setStream(stream, crop, allowBackup) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.setStream(stream, null, false, FLAG_LOCK);
+ fail("setStream(stream, crop, allowBackup, which) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+ }
+
+ /**
+ * Verify that the clearWallpaper(...) methods enforce the SET_WALLPAPER permission
+ */
+ @SmallTest
+ public void testClearWallpaper() throws IOException {
+ if (wallpaperNotSupported()) {
+ return;
+ }
+
+ try {
+ mWM.clear();
+ fail("clear() did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+
+ try {
+ mWM.clear(FLAG_SYSTEM);
+ fail("clear(which) did not enforce SET_WALLPAPER");
+ } catch (SecurityException expected) { /* expected */ }
+ }
+
+ /**
+ * Verify that reading the current wallpaper enforce the READ_WALLPAPER_INTERNAL permission.
+ * The methods concerned are:
+ * getDrawable, peekDrawable, getFastDrawable, peekFastDrawable, getWallpaperFile.
+ *
+ * These methods should throw a SecurityException, even if MANAGE_EXTERNAL_STORAGE is granted.
+ */
+ public void testReadWallpaper() {
+ if (wallpaperNotSupported()) {
+ return;
+ }
+ String message = "with no permissions, getDrawable should throw a SecurityException";
+ assertSecurityException(mWM::getDrawable, message);
+ assertSecurityException(() -> mWM.getDrawable(FLAG_SYSTEM), message);
+ assertSecurityException(() -> mWM.getDrawable(FLAG_LOCK), message);
+
+ message = "with no permissions, peekDrawable should throw a SecurityException";
+ assertSecurityException(mWM::peekDrawable, message);
+ assertSecurityException(() -> mWM.peekDrawable(FLAG_SYSTEM), message);
+ assertSecurityException(() -> mWM.peekDrawable(FLAG_LOCK), message);
+
+ message = "with no permissions, getFastDrawable should throw a SecurityException";
+ assertSecurityException(mWM::getFastDrawable, message);
+ assertSecurityException(() -> mWM.getFastDrawable(FLAG_SYSTEM), message);
+ assertSecurityException(() -> mWM.getFastDrawable(FLAG_LOCK), message);
+
+ message = "with no permissions, peekFastDrawable should throw a SecurityException";
+ assertSecurityException(mWM::peekFastDrawable, message);
+ assertSecurityException(() -> mWM.peekFastDrawable(FLAG_SYSTEM), message);
+ assertSecurityException(() -> mWM.peekFastDrawable(FLAG_LOCK), message);
+
+ message = "with no permissions, getWallpaperFile should throw a SecurityException";
+ assertSecurityException(() -> mWM.getWallpaperFile(FLAG_SYSTEM), message);
+ assertSecurityException(() -> mWM.getWallpaperFile(FLAG_LOCK), message);
+ }
+
+ // ---------- Utility methods ----------
+
+ private boolean wallpaperNotSupported() {
+ return !(mWM.isWallpaperSupported() && mWM.isSetWallpaperAllowed());
+ }
+
+ private void assertSecurityException(ThrowingRunnable runnable, String errorMessage) {
+ assertThrows(errorMessage, SecurityException.class, runnable);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java b/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
new file mode 100644
index 000000000..9fff22747
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Verify WifiManager related methods without specific Wifi state permissions.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot access the WifiManager")
+@SmallTest
+public class NoWifiStatePermissionTest {
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ private static final int TEST_NET_ID = 1;
+ private static final WifiConfiguration TEST_WIFI_CONFIGURATION = new WifiConfiguration();
+ private WifiManager mWifiManager;
+
+ @Before
+ public void setUp() {
+ boolean hasWifi = sContext.getPackageManager().hasSystemFeature(FEATURE_WIFI);
+ assumeTrue(hasWifi);
+
+ mWifiManager = (WifiManager) sContext.getSystemService(Context.WIFI_SERVICE);
+ assertNotNull(mWifiManager);
+ }
+
+ /**
+ * Verify that WifiManager#getWifiState() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testGetWifiState() {
+ mWifiManager.getWifiState();
+ }
+
+ /**
+ * Verify that WifiManager#getConfiguredNetworks() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testGetConfiguredNetworks() {
+ mWifiManager.getConfiguredNetworks();
+ }
+
+ /**
+ * Verify that WifiManager#getConnectionInfo() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testGetConnectionInfo() {
+ mWifiManager.getConnectionInfo();
+ }
+
+ /**
+ * Verify that WifiManager#getScanResults() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testGetScanResults() {
+ mWifiManager.getScanResults();
+ }
+
+ /**
+ * Verify that WifiManager#getDhcpInfo() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testGetDhcpInfo() {
+ mWifiManager.getDhcpInfo();
+ }
+
+ /**
+ * Verify that WifiManager#disconnect() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testDisconnect() {
+ mWifiManager.disconnect();
+ }
+
+ /**
+ * Verify that WifiManager#reconnect() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testReconnect() {
+ mWifiManager.reconnect();
+ }
+
+ /**
+ * Verify that WifiManager#reassociate() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testReassociate() {
+ mWifiManager.reassociate();
+ }
+
+ /**
+ * Verify that WifiManager#addNetwork() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testAddNetwork() {
+ mWifiManager.addNetwork(TEST_WIFI_CONFIGURATION);
+ }
+
+ /**
+ * Verify that WifiManager#updateNetwork() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testUpdateNetwork() {
+ TEST_WIFI_CONFIGURATION.networkId = 2;
+ mWifiManager.updateNetwork(TEST_WIFI_CONFIGURATION);
+ }
+ /**
+ * Verify that WifiManager#removeNetwork() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testRemoveNetwork() {
+ mWifiManager.removeNetwork(TEST_NET_ID);
+ }
+
+ /**
+ * Verify that WifiManager#enableNetwork() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testEnableNetwork() {
+ mWifiManager.enableNetwork(TEST_NET_ID, false);
+ }
+
+ /**
+ * Verify that WifiManager#disableNetwork() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testDisableNetwork() {
+ mWifiManager.disableNetwork(TEST_NET_ID);
+ }
+
+ /**
+ * Verify that WifiManager#pingSupplicant() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testPingSupplicant() {
+ mWifiManager.pingSupplicant();
+ }
+
+ /**
+ * Verify that WifiManager#startScan() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testStartScan() {
+ mWifiManager.startScan();
+ }
+
+ /**
+ * Verify that WifiManager#setWifiEnabled() requires permissions.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
+ */
+ @Test(expected = SecurityException.class)
+ public void testSetWifiEnabled() {
+ mWifiManager.setWifiEnabled(true);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckTest.java b/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckTest.java
new file mode 100644
index 000000000..19fc20de6
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckTest.java
@@ -0,0 +1,226 @@
+/*
+ * 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.permission.cts;
+
+import static android.permission.cts.PermissionUtils.clearAppState;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+import static android.permission.cts.TestUtils.ensure;
+import static android.permission.cts.TestUtils.eventually;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.rule.ScreenRecordRule;
+import android.service.notification.StatusBarNotification;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.modules.utils.build.SdkLevel;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests the {@code NotificationListenerCheck} in permission controller.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot set system settings as instant app. Also we never show a notification"
+ + " listener check notification for instant apps.")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@ScreenRecordRule.ScreenRecord
+@FlakyTest
+public class NotificationListenerCheckTest extends BaseNotificationListenerCheckTest {
+
+ public final ScreenRecordRule mScreenRecordRule = new ScreenRecordRule(false, false);
+
+ @Before
+ public void setup() throws Throwable {
+ // Skip tests if safety center not allowed
+ assumeDeviceSupportsSafetyCenter();
+
+ wakeUpAndDismissKeyguard();
+ resetPermissionControllerBeforeEachTest();
+
+ // Cts NLS is required to verify sent Notifications, however, we don't want it to show up in
+ // testing
+ triggerAndDismissCtsNotificationListenerNotification();
+
+ clearNotifications();
+
+ // Install and allow the app with NLS for testing
+ install(TEST_APP_NOTIFICATION_LISTENER_APK);
+ allowTestAppNotificationListenerService();
+ }
+
+ @After
+ public void tearDown() throws Throwable {
+ // Disallow and uninstall the app with NLS for testing
+ disallowTestAppNotificationListenerService();
+ uninstallApp(TEST_APP_PKG);
+
+ clearNotifications();
+ }
+
+ @Test
+ public void noNotificationIfFeatureDisabled() throws Throwable {
+ setNotificationListenerCheckEnabled(false);
+
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void noNotificationIfSafetyCenterDisabled() throws Throwable {
+ SafetyCenterUtils.setSafetyCenterEnabled(false);
+
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsShown() throws Throwable {
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull("Expected notification, none found", getNotification(false)),
+ UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsShownOnlyOnce() throws Throwable {
+ runNotificationListenerCheck();
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ runNotificationListenerCheck();
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsShownAgainAfterClear() throws Throwable {
+ runNotificationListenerCheck();
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ clearAppState(TEST_APP_PKG);
+ // Wait until package is cleared and permission controller has cleared the state
+ Thread.sleep(2000);
+
+ allowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsShownAgainAfterUninstallAndReinstall() throws Throwable {
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ uninstallApp(TEST_APP_PKG);
+
+ // Wait until package permission controller has cleared the state
+ Thread.sleep(2000);
+
+ install(TEST_APP_NOTIFICATION_LISTENER_APK);
+
+ allowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsShownAgainAfterDisableAndReenableAppNotificationListener()
+ throws Throwable {
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ // Disallow NLS, and run NLS check job. This should clear NLS off notified list
+ disallowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ // Re-allow NLS, and run NLS check job. This work now that it's cleared NLS off notified
+ // list
+ allowTestAppNotificationListenerService();
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(true)), UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void removeNotificationOnUninstall() throws Throwable {
+ runNotificationListenerCheck();
+
+ eventually(() -> assertNotNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+
+ uninstallApp(TEST_APP_PKG);
+
+ // Wait until package permission controller has cleared the state
+ Thread.sleep(2000);
+
+ eventually(() -> assertNull(getNotification(false)), UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationIsNotShownAfterDisableAppNotificationListener() throws Throwable {
+ disallowTestAppNotificationListenerService();
+
+ runNotificationListenerCheck();
+
+ // We don't expect a notification, but try to trigger one anyway
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void notificationOnClick_opensSafetyCenter() throws Throwable {
+ runNotificationListenerCheck();
+
+ StatusBarNotification currentNotification = eventually(
+ () -> {
+ StatusBarNotification notification = getNotification(false);
+ assertNotNull(notification);
+ return notification;
+ }, UNEXPECTED_TIMEOUT_MILLIS);
+
+ // Verify content intent
+ PendingIntent contentIntent = currentNotification.getNotification().contentIntent;
+ if (SdkLevel.isAtLeastU()) {
+ contentIntent.send(null, 0, null, null, null, null,
+ ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle());
+ } else {
+ contentIntent.send();
+ }
+
+ SafetyCenterUtils.assertSafetyCenterStarted();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckWithSafetyCenterUnsupportedTest.java b/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckWithSafetyCenterUnsupportedTest.java
new file mode 100644
index 000000000..a346de6fd
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/NotificationListenerCheckWithSafetyCenterUnsupportedTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.permission.cts;
+
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+import static android.permission.cts.TestUtils.ensure;
+
+import static org.junit.Assert.assertNull;
+
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests the {@code NotificationListenerCheck} in permission controller.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot set system settings as instant app. Also we never show a notification"
+ + " listener check notification for instant apps.")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+public class NotificationListenerCheckWithSafetyCenterUnsupportedTest
+ extends BaseNotificationListenerCheckTest {
+
+ @Before
+ public void setup() throws Throwable {
+ // Skip tests if safety center is supported
+ assumeDeviceDoesNotSupportSafetyCenter();
+
+ wakeUpAndDismissKeyguard();
+ resetPermissionControllerBeforeEachTest();
+
+ clearNotifications();
+
+ // Install and allow the app with NLS for testing
+ install(TEST_APP_NOTIFICATION_LISTENER_APK);
+ allowTestAppNotificationListenerService();
+ }
+
+ @After
+ public void tearDown() throws Throwable {
+ // Disallow and uninstall the app with NLS for testing
+ disallowTestAppNotificationListenerService();
+ uninstallApp(TEST_APP_PKG);
+
+ clearNotifications();
+ }
+
+ @Test
+ public void noNotifications_featureEnabled_safetyCenterEnabled() throws Throwable {
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void noNotifications_featureDisabled_safetyCenterEnabled() throws Throwable {
+ setNotificationListenerCheckEnabled(false);
+
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void noNotifications_featureEnabled_safetyCenterDisabled() throws Throwable {
+ SafetyCenterUtils.setSafetyCenterEnabled(false);
+
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void noNotifications_featureDisabled_safetyCenterDisabled() throws Throwable {
+ setNotificationListenerCheckEnabled(false);
+ SafetyCenterUtils.setSafetyCenterEnabled(false);
+
+ runNotificationListenerCheck();
+
+ ensure(() -> assertNull("Expected no notifications", getNotification(false)),
+ ENSURE_NOTIFICATION_NOT_SHOWN_EXPECTED_TIMEOUT_MILLIS);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/OneTimePermissionTest.java b/tests/cts/permission/src/android/permission/cts/OneTimePermissionTest.java
new file mode 100644
index 000000000..1410434a7
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/OneTimePermissionTest.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.CAMERA;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assume.assumeFalse;
+
+import android.app.ActivityManager;
+import android.app.DreamManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.rule.ScreenRecordRule;
+import android.provider.DeviceConfig;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.compatibility.common.util.FeatureUtil;
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.UiAutomatorUtils2;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@ScreenRecordRule.ScreenRecord
+public class OneTimePermissionTest {
+
+ private static final String APP_PKG_NAME = "android.permission.cts.appthatrequestpermission";
+ private static final String CUSTOM_CAMERA_PERM_APP_PKG_NAME =
+ "android.permission.cts.appthatrequestcustomcamerapermission";
+ private static final String APK =
+ "/data/local/tmp/cts-permission/CtsAppThatRequestsOneTimePermission.apk";
+ private static final String CUSTOM_CAMERA_PERM_APK =
+ "/data/local/tmp/cts-permission/CtsAppThatRequestCustomCameraPermission.apk";
+ private static final String EXTRA_FOREGROUND_SERVICE_LIFESPAN =
+ "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_LIFESPAN";
+ private static final String EXTRA_FOREGROUND_SERVICE_STICKY =
+ "android.permission.cts.OneTimePermissionTest.EXTRA_FOREGROUND_SERVICE_STICKY";
+
+ public static final String CUSTOM_PERMISSION = "appthatrequestcustomcamerapermission.CUSTOM";
+
+ private static final long ONE_TIME_TIMEOUT_MILLIS = 5000;
+ private static final long ONE_TIME_KILLED_DELAY_MILLIS = 5000;
+ private static final long ONE_TIME_TIMER_LOWER_GRACE_PERIOD = 1000;
+ private static final long ONE_TIME_TIMER_UPPER_GRACE_PERIOD = 10000;
+
+ private final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private final PackageManager mPackageManager = mContext.getPackageManager();
+ private final UiDevice mUiDevice =
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ private final ActivityManager mActivityManager =
+ mContext.getSystemService(ActivityManager.class);
+ private String mOldOneTimePermissionTimeoutValue;
+ private String mOldOneTimePermissionKilledDelayValue;
+
+ @Rule
+ public final ScreenRecordRule sScreenRecordRule = new ScreenRecordRule(false, false);
+
+ @Rule
+ public IgnoreAllTestsRule mIgnoreAutomotive = new IgnoreAllTestsRule(
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+
+ @Before
+ public void wakeUpScreen() {
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+
+ SystemUtil.runShellCommand("input keyevent 82");
+ }
+
+ @Before
+ public void installApp() {
+ runShellCommandOrThrow("pm install -r " + APK);
+ runShellCommandOrThrow("pm install -r " + CUSTOM_CAMERA_PERM_APK);
+ }
+
+ @Before
+ public void prepareDeviceForOneTime() {
+ runWithShellPermissionIdentity(() -> {
+ mOldOneTimePermissionTimeoutValue = DeviceConfig.getProperty("permissions",
+ "one_time_permissions_timeout_millis");
+ mOldOneTimePermissionKilledDelayValue = DeviceConfig.getProperty("permissions",
+ "one_time_permissions_killed_delay_millis");
+ DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+ Long.toString(ONE_TIME_TIMEOUT_MILLIS), false);
+ DeviceConfig.setProperty("permissions",
+ "one_time_permissions_killed_delay_millis",
+ Long.toString(ONE_TIME_KILLED_DELAY_MILLIS), false);
+ });
+ }
+
+ @After
+ public void uninstallApp() {
+ runShellCommand("pm uninstall " + APP_PKG_NAME);
+ runShellCommand("pm uninstall " + CUSTOM_CAMERA_PERM_APP_PKG_NAME);
+ }
+
+ @After
+ public void restoreDeviceForOneTime() {
+ runWithShellPermissionIdentity(
+ () -> {
+ DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+ mOldOneTimePermissionTimeoutValue, false);
+ DeviceConfig.setProperty("permissions",
+ "one_time_permissions_killed_delay_millis",
+ mOldOneTimePermissionKilledDelayValue, false);
+ });
+ }
+
+ @Test
+ public void testOneTimePermission() throws Throwable {
+ startApp();
+
+ CompletableFuture<Long> exitTime = registerAppExitListener();
+
+ clickOneTimeButton();
+
+ exitApp();
+
+ assertGranted(5000);
+
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD);
+
+ assertExpectedLifespan(exitTime, ONE_TIME_TIMEOUT_MILLIS);
+ }
+
+ @Ignore
+ @Test
+ public void testForegroundServiceMaintainsPermission() throws Throwable {
+ startApp();
+
+ CompletableFuture<Long> exitTime = registerAppExitListener();
+
+ clickOneTimeButton();
+
+ long expectedLifespanMillis = 2 * ONE_TIME_TIMEOUT_MILLIS;
+ startAppForegroundService(expectedLifespanMillis, false);
+
+ exitApp();
+
+ assertGranted(5000);
+
+ assertDenied(expectedLifespanMillis + ONE_TIME_TIMER_UPPER_GRACE_PERIOD);
+
+ assertExpectedLifespan(exitTime, expectedLifespanMillis);
+
+ }
+
+ @Test
+ public void testPermissionRevokedOnKill() throws Throwable {
+ startApp();
+
+ clickOneTimeButton();
+
+ exitApp();
+
+ assertGranted(5000);
+
+ mUiDevice.waitForIdle();
+ SystemUtil.runWithShellPermissionIdentity(() ->
+ mActivityManager.killBackgroundProcesses(APP_PKG_NAME));
+
+ runWithShellPermissionIdentity(
+ () -> Thread.sleep(DeviceConfig.getLong(DeviceConfig.NAMESPACE_PERMISSIONS,
+ "one_time_permissions_killed_delay_millis", 5000L)));
+ assertDenied(500);
+ }
+
+ @Test
+ @FlakyTest
+ public void testStickyServiceMaintainsPermissionOnRestart() throws Throwable {
+ startApp();
+
+ clickOneTimeButton();
+
+ startAppForegroundService(2 * ONE_TIME_TIMEOUT_MILLIS, true);
+
+ exitApp();
+
+ assertGranted(5000);
+ mUiDevice.waitForIdle();
+ Thread.sleep(ONE_TIME_TIMEOUT_MILLIS);
+
+ runShellCommand("am crash " + APP_PKG_NAME);
+
+ eventually(() -> runWithShellPermissionIdentity(() -> {
+ if (mActivityManager.getPackageImportance(APP_PKG_NAME) <= IMPORTANCE_CACHED) {
+ throw new AssertionError("App was never killed");
+ }
+ }));
+
+ eventually(() -> runWithShellPermissionIdentity(() -> {
+ if (mActivityManager.getPackageImportance(APP_PKG_NAME)
+ > IMPORTANCE_FOREGROUND_SERVICE) {
+ throw new AssertionError("Foreground service never resumed");
+ }
+ Assert.assertEquals("Service resumed without permission",
+ PackageManager.PERMISSION_GRANTED, mContext.getPackageManager()
+ .checkPermission(ACCESS_FINE_LOCATION, APP_PKG_NAME));
+ }));
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 237405974L)
+ public void testCustomPermissionIsGrantedOneTime() throws Throwable {
+ startApp(new ComponentName(CUSTOM_CAMERA_PERM_APP_PKG_NAME,
+ CUSTOM_CAMERA_PERM_APP_PKG_NAME + ".RequestCameraPermission"));
+
+ // We're only manually granting CAMERA, but the app will later request CUSTOM and get it
+ // granted silently. This is intentional since it's in the same group but both should
+ // eventually be revoked
+ clickOneTimeButton();
+
+ // Just waiting for the revocation
+ eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mContext.getPackageManager()
+ .checkPermission(CAMERA, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+ // This checks the vulnerability
+ eventually(() -> Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mContext.getPackageManager()
+ .checkPermission(CUSTOM_PERMISSION, CUSTOM_CAMERA_PERM_APP_PKG_NAME)));
+
+ }
+
+ private void assertGrantedState(String s, int permissionGranted, long timeoutMillis) {
+ eventually(() -> Assert.assertEquals(s,
+ permissionGranted, mPackageManager
+ .checkPermission(ACCESS_FINE_LOCATION, APP_PKG_NAME)), timeoutMillis);
+ }
+
+ private void assertGranted(long timeoutMillis) {
+ assertGrantedState("Permission was never granted", PackageManager.PERMISSION_GRANTED,
+ timeoutMillis);
+ }
+
+ private void assertDenied(long timeoutMillis) {
+ assertGrantedState("Permission was never revoked", PackageManager.PERMISSION_DENIED,
+ timeoutMillis);
+ }
+
+ private void assertExpectedLifespan(CompletableFuture<Long> exitTime, long expectedLifespan)
+ throws InterruptedException, java.util.concurrent.ExecutionException,
+ java.util.concurrent.TimeoutException {
+ long grantedLength = System.currentTimeMillis() - exitTime.get(0, TimeUnit.MILLISECONDS);
+ if (grantedLength + ONE_TIME_TIMER_LOWER_GRACE_PERIOD < expectedLifespan) {
+ throw new AssertionError(
+ "The one time permission lived shorter than expected. expected: "
+ + expectedLifespan + "ms but was: " + grantedLength + "ms");
+ }
+ }
+
+ private void exitApp() {
+ boolean[] hasExited = {false};
+ try {
+ new Thread(() -> {
+ while (!hasExited[0]) {
+ DreamManager mDreamManager = mContext.getSystemService(DreamManager.class);
+ mUiDevice.pressHome();
+ mUiDevice.pressBack();
+ runWithShellPermissionIdentity(() -> {
+ if (mDreamManager.isDreaming()) {
+ mDreamManager.stopDream();
+ }
+ });
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }).start();
+ eventually(() -> {
+ runWithShellPermissionIdentity(() -> {
+ if (mActivityManager.getPackageImportance(APP_PKG_NAME)
+ <= IMPORTANCE_FOREGROUND) {
+ throw new AssertionError("Unable to exit application");
+ }
+ });
+ });
+ } finally {
+ hasExited[0] = true;
+ }
+ }
+
+ private void clickOneTimeButton() throws Throwable {
+ final UiObject2 uiObject = UiAutomatorUtils2.waitFindObject(By.res(
+ "com.android.permissioncontroller:id/permission_allow_one_time_button"), 10000);
+ Thread.sleep(500);
+ uiObject.click();
+ }
+
+ /**
+ * Start the app. The app will request the permissions.
+ */
+ private void startApp(ComponentName componentName) {
+ // One time permission is not applicable for Wear OS.
+ // The only permissions available are Allow or Deny
+ assumeFalse(
+ "Skipping test: One time permission is not supported in Wear OS",
+ FeatureUtil.isWatch());
+ Intent startApp = new Intent();
+ startApp.setComponent(componentName);
+ startApp.setFlags(FLAG_ACTIVITY_NEW_TASK);
+
+ mContext.startActivity(startApp);
+ }
+
+ /**
+ * Start the default app for these tests. The app will request the permissions.
+ */
+ private void startApp() {
+ startApp(new ComponentName(APP_PKG_NAME, APP_PKG_NAME + ".RequestPermission"));
+ }
+
+ private void startAppForegroundService(long lifespanMillis, boolean sticky) {
+ Intent intent = new Intent()
+ .setComponent(new ComponentName(
+ APP_PKG_NAME, APP_PKG_NAME + ".KeepAliveForegroundService"))
+ .putExtra(EXTRA_FOREGROUND_SERVICE_LIFESPAN, lifespanMillis)
+ .putExtra(EXTRA_FOREGROUND_SERVICE_STICKY, sticky);
+ mContext.startService(intent);
+ }
+
+ private CompletableFuture<Long> registerAppExitListener() {
+ CompletableFuture<Long> exitTimeCallback = new CompletableFuture<>();
+ try {
+ int uid = mContext.getPackageManager().getPackageUid(APP_PKG_NAME, 0);
+ runWithShellPermissionIdentity(() ->
+ mActivityManager.addOnUidImportanceListener(new SingleAppExitListener(
+ uid, IMPORTANCE_FOREGROUND, exitTimeCallback), IMPORTANCE_FOREGROUND));
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new AssertionError("Package not found.", e);
+ }
+ return exitTimeCallback;
+ }
+
+ private class SingleAppExitListener implements ActivityManager.OnUidImportanceListener {
+
+ private final int mUid;
+ private final int mImportance;
+ private final CompletableFuture<Long> mCallback;
+
+ SingleAppExitListener(int uid, int importance, CompletableFuture<Long> callback) {
+ mUid = uid;
+ mImportance = importance;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onUidImportance(int uid, int importance) {
+ if (uid == mUid && importance > mImportance) {
+ mCallback.complete(System.currentTimeMillis());
+ mActivityManager.removeOnUidImportanceListener(this);
+ }
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
new file mode 100644
index 000000000..df3ec3c64
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify the PackageManager related operations require specific permissions.
+ */
+@SmallTest
+public class PackageManagerRequiringPermissionsTest extends AndroidTestCase {
+ // Must be a known-present application package other than the one hosting this class
+ private static final String PACKAGE_NAME = "android";
+
+ private PackageManager mPackageManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPackageManager = getContext().getPackageManager();
+ assertNotNull(mPackageManager);
+ }
+
+ /**
+ * Verify that PackageManager.setApplicationEnabledSetting requires permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#CHANGE_COMPONENT_ENABLED_STATE}.
+ */
+ public void testSetApplicationEnabledSetting() {
+ try {
+ mPackageManager.setApplicationEnabledSetting(PACKAGE_NAME,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ fail("PackageManager.setApplicationEnabledSetting did not throw SecurityException as"
+ + "expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that PackageManager.addPreferredActivity requires permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#SET_PREFERRED_APPLICATIONS}.
+ */
+ public void testAddPreferredActivity() {
+ try {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
+ filter.addCategory(Intent.CATEGORY_HOME);
+ mPackageManager.addPreferredActivity(filter, 0, null, null);
+ fail("PackageManager.addPreferredActivity did not throw" +
+ " SecurityException as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that PackageManager.clearPackagePreferredActivities requires permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#SET_PREFERRED_APPLICATIONS}.
+ */
+ @AppModeFull(reason = "clearPackagePreferredActivities always returns null for instant apps "
+ + "(it does not even check for permissions)")
+ public void testClearPackagePreferredActivities() {
+ try {
+ mPackageManager.clearPackagePreferredActivities(null);
+ fail("PackageManager.clearPackagePreferredActivities did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that PackageManager.verifyPendingInstall requires permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
+ */
+ public void testVerifyPendingInstall() {
+ try {
+ mPackageManager.verifyPendingInstall(1, 1);
+ fail("PackageManager.verifyPendingInstall did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that PackageManager.extendVerificationTimeout requires permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}.
+ */
+ public void testExtendVerificationTimeout() {
+ try {
+ mPackageManager.extendVerificationTimeout(1, 1, 10000);
+ fail("PackageManager.extendVerificationTimeout did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionControllerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionControllerTest.java
new file mode 100644
index 000000000..05b45c9b1
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionControllerTest.java
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.BODY_SENSORS;
+import static android.Manifest.permission.READ_CALENDAR;
+import static android.Manifest.permission.READ_CONTACTS;
+import static android.Manifest.permission.WRITE_CALENDAR;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.permissionToOp;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
+import static android.permission.PermissionControllerManager.REASON_INSTALLER_POLICY_VIOLATION;
+import static android.permission.PermissionControllerManager.REASON_MALWARE;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permission.cts.PermissionUtils.isPermissionGranted;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.util.Collections.singletonList;
+
+import android.app.AppOpsManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.pm.PermissionGroupInfo;
+import android.permission.PermissionControllerManager;
+import android.permission.RuntimePermissionPresentationInfo;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Test {@link PermissionControllerManager}
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot talk to permission controller")
+public class PermissionControllerTest {
+ private static final String APK =
+ "/data/local/tmp/cts-permission/CtsAppThatAccessesLocationOnCommand.apk";
+ private static final String APP = "android.permission.cts.appthataccesseslocation";
+ private static final String APK2 =
+ "/data/local/tmp/cts-permission/"
+ + "CtsAppThatRequestsCalendarContactsBodySensorCustomPermission.apk";
+ private static final String APP2 = "android.permission.cts.appthatrequestcustompermission";
+ private static final String CUSTOM_PERMISSION =
+ "android.permission.cts.appthatrequestcustompermission.TEST_PERMISSION";
+
+ private static final UiAutomation sUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private static final PermissionControllerManager sController =
+ sContext.getSystemService(PermissionControllerManager.class);
+
+ @Before
+ @After
+ public void resetAppState() {
+ runWithShellPermissionIdentity(() -> {
+ sUiAutomation.grantRuntimePermission(APP, ACCESS_FINE_LOCATION);
+ sUiAutomation.grantRuntimePermission(APP, ACCESS_BACKGROUND_LOCATION);
+ setAppOp(APP, ACCESS_FINE_LOCATION, MODE_ALLOWED);
+ });
+ }
+
+ @BeforeClass
+ public static void installApp() {
+ runShellCommandOrThrow("pm install -r -g " + APK);
+ runShellCommandOrThrow("pm install -r " + APK2);
+ }
+
+ @AfterClass
+ public static void uninstallApp() {
+ runShellCommand("pm uninstall " + APP);
+ runShellCommand("pm uninstall " + APP2);
+ }
+
+ private @NonNull Map<String, List<String>> revokePermissions(
+ @NonNull Map<String, List<String>> request, boolean doDryRun, int reason,
+ @NonNull Executor executor) throws Exception {
+ AtomicReference<Map<String, List<String>>> result = new AtomicReference<>();
+
+ sController.revokeRuntimePermissions(request, doDryRun, reason, executor,
+ new PermissionControllerManager.OnRevokeRuntimePermissionsCallback() {
+ @Override
+ public void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> r) {
+ synchronized (result) {
+ result.set(r);
+ result.notifyAll();
+ }
+ }
+ });
+
+ synchronized (result) {
+ while (result.get() == null) {
+ result.wait();
+ }
+ }
+
+ return result.get();
+ }
+
+ private @NonNull Map<String, List<String>> revokePermissions(
+ @NonNull Map<String, List<String>> request, boolean doDryRun, boolean adoptShell)
+ throws Exception {
+ if (adoptShell) {
+ Map<String, List<String>> revokeRet =
+ callWithShellPermissionIdentity(() -> revokePermissions(
+ request, doDryRun, REASON_MALWARE, sContext.getMainExecutor()));
+ return revokeRet;
+ }
+ return revokePermissions(request, doDryRun, REASON_MALWARE, sContext.getMainExecutor());
+ }
+
+ private @NonNull Map<String, List<String>> revokePermissions(
+ @NonNull Map<String, List<String>> request, boolean doDryRun) throws Exception {
+ return revokePermissions(request, doDryRun, true);
+ }
+
+ private void setAppOp(@NonNull String pkg, @NonNull String perm, int mode) throws Exception {
+ sContext.getSystemService(AppOpsManager.class).setUidMode(permissionToOp(perm),
+ sContext.getPackageManager().getPackageUid(pkg, 0), mode);
+ }
+
+ private Map<String, List<String>> buildRevokeRequest(@NonNull String app,
+ @NonNull String permission) {
+ return Collections.singletonMap(app, singletonList(permission));
+ }
+
+ private void assertRuntimePermissionLabelsAreValid(List<String> runtimePermissions,
+ List<RuntimePermissionPresentationInfo> permissionInfos, int expectedRuntimeGranted,
+ String app) throws Exception {
+ int numRuntimeGranted = 0;
+ for (String permission : runtimePermissions) {
+ if (isPermissionGranted(app, permission)) {
+ numRuntimeGranted++;
+ }
+ }
+ assertThat(numRuntimeGranted).isEqualTo(expectedRuntimeGranted);
+
+ ArrayList<CharSequence> maybeStandardPermissionLabels = new ArrayList<>();
+ ArrayList<CharSequence> nonStandardPermissionLabels = new ArrayList<>();
+ for (PermissionGroupInfo permGroup : sContext.getPackageManager().getAllPermissionGroups(
+ 0)) {
+ CharSequence permissionGroupLabel = permGroup.loadLabel(sContext.getPackageManager());
+ if (permGroup.packageName.equals("android")) {
+ maybeStandardPermissionLabels.add(permissionGroupLabel);
+ } else {
+ nonStandardPermissionLabels.add(permissionGroupLabel);
+ }
+ }
+
+ int numInfosGranted = 0;
+
+ for (RuntimePermissionPresentationInfo permissionInfo : permissionInfos) {
+ CharSequence permissionGroupLabel = permissionInfo.getLabel();
+
+ // PermissionInfo should be included in exactly one of existing (possibly) standard
+ // or nonstandard permission groups
+ if (permissionInfo.isStandard()) {
+ assertThat(maybeStandardPermissionLabels).contains(permissionGroupLabel);
+ } else {
+ assertThat(nonStandardPermissionLabels).contains(permissionGroupLabel);
+ }
+ if (permissionInfo.isGranted()) {
+ numInfosGranted++;
+ }
+ }
+
+ // Each permissionInfo represents one or more runtime permissions, but we don't have a
+ // mapping, so we check that we have at least as many runtimePermissions as permissionInfos
+ assertThat(numRuntimeGranted).isAtLeast(numInfosGranted);
+ }
+
+ @Test
+ public void revokePermissionsDryRunSinglePermission() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ Map<String, List<String>> result = revokePermissions(request, true);
+
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.get(APP)).isNotNull();
+ assertThat(result.get(APP)).containsExactly(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ @Test
+ public void revokePermissionsSinglePermission() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ revokePermissions(request, false);
+
+ assertThat(sContext.getPackageManager().checkPermission(ACCESS_BACKGROUND_LOCATION,
+ APP)).isEqualTo(PERMISSION_DENIED);
+ }
+
+ @Test
+ public void revokePermissionsDoNotAlreadyRevokedPermission() throws Exception {
+ // Properly revoke the permission
+ runWithShellPermissionIdentity(() -> {
+ sUiAutomation.revokeRuntimePermission(APP, ACCESS_BACKGROUND_LOCATION);
+ setAppOp(APP, ACCESS_FINE_LOCATION, MODE_FOREGROUND);
+ });
+
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+ Map<String, List<String>> result = revokePermissions(request, false);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void revokePermissionsDryRunForegroundPermission() throws Exception {
+ assertThat(sContext.getPackageManager().checkPermission(ACCESS_FINE_LOCATION,
+ APP)).isEqualTo(PERMISSION_GRANTED);
+
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_FINE_LOCATION);
+ Map<String, List<String>> result = revokePermissions(request, true);
+
+ assertThat(result.size()).isEqualTo(1);
+ assertThat(result.get(APP)).isNotNull();
+ assertThat(result.get(APP)).containsExactly(ACCESS_FINE_LOCATION,
+ ACCESS_BACKGROUND_LOCATION, ACCESS_COARSE_LOCATION);
+ }
+
+ @Test
+ public void revokePermissionsUnrequestedPermission() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, READ_CONTACTS);
+
+ Map<String, List<String>> result = revokePermissions(request, false);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void revokeFromUnknownPackage() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest("invalid.app", READ_CONTACTS);
+
+ Map<String, List<String>> result = revokePermissions(request, false);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void revokePermissionsFromUnknownPermission() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, "unknown.permission");
+
+ Map<String, List<String>> result = revokePermissions(request, false);
+
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void revokePermissionsPolicyViolationFromWrongPackage() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_FINE_LOCATION);
+ Map<String, List<String>> result = callWithShellPermissionIdentity(
+ () -> revokePermissions(request,
+ false, REASON_INSTALLER_POLICY_VIOLATION, sContext.getMainExecutor()));
+ assertThat(result).isEmpty();
+ }
+
+ @Test
+ public void revokePermissionsWithExecutorForCallback() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ AtomicBoolean wasRunOnExecutor = new AtomicBoolean();
+ runWithShellPermissionIdentity(() ->
+ revokePermissions(request, true, REASON_MALWARE, command -> {
+ wasRunOnExecutor.set(true);
+ command.run();
+ }));
+
+ assertThat(wasRunOnExecutor.get()).isTrue();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullPkg() throws Exception {
+ Map<String, List<String>> request = Collections.singletonMap(null,
+ singletonList(ACCESS_FINE_LOCATION));
+
+ revokePermissions(request, true);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullPermissions() throws Exception {
+ Map<String, List<String>> request = Collections.singletonMap(APP, null);
+
+ revokePermissions(request, true);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullPermission() throws Exception {
+ Map<String, List<String>> request = Collections.singletonMap(APP,
+ singletonList(null));
+
+ revokePermissions(request, true);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullRequests() {
+ sController.revokeRuntimePermissions(null, false, REASON_MALWARE,
+ sContext.getMainExecutor(),
+ new PermissionControllerManager.OnRevokeRuntimePermissionsCallback() {
+ @Override
+ public void onRevokeRuntimePermissions(
+ @NonNull Map<String, List<String>> revoked) {
+ }
+ });
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullCallback() {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ sController.revokeRuntimePermissions(request, false, REASON_MALWARE,
+ sContext.getMainExecutor(), null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionsWithNullExecutor() {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ sController.revokeRuntimePermissions(request, false, REASON_MALWARE, null,
+ new PermissionControllerManager.OnRevokeRuntimePermissionsCallback() {
+ @Override
+ public void onRevokeRuntimePermissions(
+ @NonNull Map<String, List<String>> revoked) {
+
+ }
+ });
+ }
+
+ @Test(expected = SecurityException.class)
+ public void revokePermissionsWithoutPermission() throws Exception {
+ Map<String, List<String>> request = buildRevokeRequest(APP, ACCESS_BACKGROUND_LOCATION);
+
+ // This will fail as the test-app does not have the required permission
+ revokePermissions(request, true, false);
+ }
+
+ @Test
+ public void getAppPermissionsForApp() throws Exception {
+ CompletableFuture<List<RuntimePermissionPresentationInfo>> futurePermissionInfos =
+ new CompletableFuture<>();
+
+ List<String> runtimePermissions;
+ List<RuntimePermissionPresentationInfo> permissionInfos;
+
+ sUiAutomation.adoptShellPermissionIdentity();
+ try {
+ sController.getAppPermissions(APP, futurePermissionInfos::complete, null);
+ runtimePermissions = PermissionUtils.getRuntimePermissions(APP);
+ assertThat(runtimePermissions).isNotEmpty();
+ permissionInfos = futurePermissionInfos.get();
+ } finally {
+ sUiAutomation.dropShellPermissionIdentity();
+ }
+
+ assertRuntimePermissionLabelsAreValid(runtimePermissions, permissionInfos, 3, APP);
+ }
+
+ @Test
+ public void getAppPermissionsForCustomApp() throws Exception {
+ CompletableFuture<List<RuntimePermissionPresentationInfo>> futurePermissionInfos =
+ new CompletableFuture<>();
+
+ // Grant all requested permissions except READ_CALENDAR
+ sUiAutomation.grantRuntimePermission(APP2, CUSTOM_PERMISSION);
+ PermissionUtils.grantPermission(APP2, BODY_SENSORS);
+ PermissionUtils.grantPermission(APP2, READ_CONTACTS);
+ PermissionUtils.grantPermission(APP2, WRITE_CALENDAR);
+
+ List<String> runtimePermissions;
+ List<RuntimePermissionPresentationInfo> permissionInfos;
+ sUiAutomation.adoptShellPermissionIdentity();
+ try {
+ sController.getAppPermissions(APP2, futurePermissionInfos::complete, null);
+ runtimePermissions = PermissionUtils.getRuntimePermissions(APP2);
+
+ permissionInfos = futurePermissionInfos.get();
+ } finally {
+ sUiAutomation.dropShellPermissionIdentity();
+ }
+
+ assertThat(permissionInfos).isNotEmpty();
+ assertThat(runtimePermissions.size()).isEqualTo(5);
+ assertRuntimePermissionLabelsAreValid(runtimePermissions, permissionInfos, 4, APP2);
+ }
+
+ @Test
+ public void revokePermissionAutomaticallyExtendsToWholeGroup() throws Exception {
+ grantPermission(APP2, READ_CALENDAR);
+ grantPermission(APP2, WRITE_CALENDAR);
+
+ runWithShellPermissionIdentity(
+ () -> {
+ sController.revokeRuntimePermission(APP2, READ_CALENDAR);
+
+ eventually(() -> {
+ assertThat(isGranted(APP2, READ_CALENDAR)).isEqualTo(false);
+ // revokePermission automatically extends the revocation to whole group
+ assertThat(isGranted(APP2, WRITE_CALENDAR)).isEqualTo(false);
+ });
+ });
+ }
+
+ @Test
+ public void revokePermissionCustom() throws Exception {
+ sUiAutomation.grantRuntimePermission(APP2, CUSTOM_PERMISSION);
+
+ runWithShellPermissionIdentity(
+ () -> {
+ sController.revokeRuntimePermission(APP2, CUSTOM_PERMISSION);
+
+ eventually(() -> {
+ assertThat(isPermissionGranted(APP2, CUSTOM_PERMISSION)).isEqualTo(false);
+ });
+ });
+ }
+
+ @Test
+ public void revokePermissionWithInvalidPkg() throws Exception {
+ // No return value, call is ignored
+ runWithShellPermissionIdentity(
+ () -> sController.revokeRuntimePermission("invalid.package", READ_CALENDAR));
+ }
+
+ @Test
+ public void revokePermissionWithInvalidPermission() throws Exception {
+ // No return value, call is ignored
+ runWithShellPermissionIdentity(
+ () -> sController.revokeRuntimePermission(APP2, "invalid.permission"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionWithNullPkg() throws Exception {
+ sController.revokeRuntimePermission(null, READ_CALENDAR);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void revokePermissionWithNullPermission() throws Exception {
+ sController.revokeRuntimePermission(APP2, null);
+ }
+
+ // TODO: Add more tests for countPermissionAppsGranted when the method can be safely called
+ // multiple times in a row
+
+ @Test
+ public void countPermissionAppsGranted() {
+ runWithShellPermissionIdentity(
+ () -> {
+ CompletableFuture<Integer> numApps = new CompletableFuture<>();
+
+ sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION),
+ COUNT_ONLY_WHEN_GRANTED, numApps::complete, null);
+
+ // TODO: Better would be to count before, grant a permission, count again and
+ // then compare before and after
+ assertThat(numApps.get()).isAtLeast(1);
+ });
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void countPermissionAppsNullPermission() {
+ sController.countPermissionApps(null, 0, (n) -> { }, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void countPermissionAppsInvalidFlags() {
+ sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION), -1, (n) -> { }, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void countPermissionAppsNullCallback() {
+ sController.countPermissionApps(singletonList(ACCESS_FINE_LOCATION), 0, null, null);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionFlagsTest.java b/tests/cts/permission/src/android/permission/cts/PermissionFlagsTest.java
new file mode 100644
index 000000000..d03e215ed
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionFlagsTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.READ_CALL_LOG;
+import static android.Manifest.permission.READ_CONTACTS;
+import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.permission.cts.PermissionUtils.clearAppState;
+import static android.permission.cts.PermissionUtils.getAllPermissionFlags;
+import static android.permission.cts.PermissionUtils.getPermissionFlags;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permission.cts.PermissionUtils.setPermissionFlags;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.platform.test.annotations.PlatinumTest;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests how permission flags behave.
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Cannot read permission flags of other app.")
+@PlatinumTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class PermissionFlagsTest {
+ /** The package name of most apps used in the test */
+ private static final String APP_PKG = "android.permission.cts.appthatrequestpermission";
+ private static final String APP_SYSTEM_ALERT_WINDOW_PKG =
+ "android.permission.cts.usesystemalertwindowpermission";
+
+ private static final String TMP_DIR = "/data/local/tmp/cts-permission/";
+ private static final String APK_CONTACTS_15 =
+ TMP_DIR + "CtsAppThatRequestsContactsPermission15.apk";
+ private static final String APK_LOCATION_22 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission22.apk";
+ private static final String APK_LOCATION_28 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission28.apk";
+ private static final String APK_SYSTEM_ALERT_WINDOW_23 =
+ TMP_DIR + "CtsAppThatRequestsSystemAlertWindow23.apk";
+
+ @After
+ @Before
+ public void uninstallTestApp() {
+ uninstallApp(APP_PKG);
+ uninstallApp(APP_SYSTEM_ALERT_WINDOW_PKG);
+ }
+
+ @Test
+ public void implicitPermission() {
+ install(APK_LOCATION_28);
+
+ assertEquals(FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION));
+ }
+
+ @Test
+ public void regularPermission() {
+ install(APK_LOCATION_28);
+
+ assertEquals(0, getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION));
+ }
+
+ @Test
+ public void regularPermissionPreM() {
+ install(APK_CONTACTS_15);
+
+ assertEquals(FLAG_PERMISSION_REVIEW_REQUIRED,
+ getPermissionFlags(APP_PKG, READ_CONTACTS) & FLAG_PERMISSION_REVIEW_REQUIRED);
+ }
+
+ @Test
+ public void clearRegularPermissionPreM() {
+ install(APK_CONTACTS_15);
+
+ int defaultState = getPermissionFlags(APP_PKG, READ_CONTACTS);
+ setPermissionFlags(APP_PKG, READ_CONTACTS, FLAG_PERMISSION_REVIEW_REQUIRED, 0);
+ setPermissionFlags(APP_PKG, READ_CONTACTS,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ clearAppState(APP_PKG);
+
+ eventually(() -> assertEquals(defaultState, getPermissionFlags(APP_PKG, READ_CONTACTS)));
+ }
+
+ @Test
+ public void clearImplicitPermissionPreM() {
+ install(APK_CONTACTS_15);
+
+ int defaultState = getPermissionFlags(APP_PKG, READ_CALL_LOG);
+ setPermissionFlags(APP_PKG, READ_CALL_LOG, FLAG_PERMISSION_REVIEW_REQUIRED, 0);
+ setPermissionFlags(APP_PKG, READ_CALL_LOG,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ clearAppState(APP_PKG);
+
+ eventually(() -> assertEquals(defaultState, getPermissionFlags(APP_PKG, READ_CALL_LOG)));
+ }
+
+ @Test
+ public void clearRegularPermission() {
+ install(APK_LOCATION_28);
+
+ int defaultState = getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION);
+ setPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ clearAppState(APP_PKG);
+
+ eventually(() -> assertEquals(defaultState,
+ getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION)));
+ }
+
+ @Test
+ public void clearImplicitPermission() {
+ install(APK_LOCATION_28);
+
+ int defaultState = getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+ setPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ clearAppState(APP_PKG);
+
+ eventually(() -> assertEquals(defaultState,
+ getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION)));
+ }
+
+ @Test
+ public void reinstallPreM() {
+ install(APK_CONTACTS_15);
+ install(APK_CONTACTS_15);
+
+ assertEquals(FLAG_PERMISSION_REVIEW_REQUIRED,
+ getPermissionFlags(APP_PKG, READ_CONTACTS) & FLAG_PERMISSION_REVIEW_REQUIRED);
+ }
+
+ @Test
+ public void reinstallDoesNotOverrideChangesPreM() {
+ install(APK_CONTACTS_15);
+
+ setPermissionFlags(APP_PKG, READ_CONTACTS, FLAG_PERMISSION_REVIEW_REQUIRED, 0);
+ setPermissionFlags(APP_PKG, READ_CONTACTS,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ install(APK_CONTACTS_15);
+
+ assertEquals(FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ getPermissionFlags(APP_PKG, READ_CONTACTS) & (FLAG_PERMISSION_USER_SET
+ | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_REVIEW_REQUIRED));
+ }
+
+ @Test
+ public void reinstall() {
+ install(APK_LOCATION_28);
+ install(APK_LOCATION_28);
+
+ assertEquals(0, getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION));
+ assertEquals(FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION));
+ }
+
+ @Test
+ public void reinstallDoesNotOverrideChanges() {
+ install(APK_LOCATION_28);
+
+ setPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+ setPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED);
+
+ install(APK_LOCATION_28);
+
+ assertEquals(FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED,
+ getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION));
+
+ assertEquals(FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED
+ | FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION));
+ }
+
+ @Test
+ public void revokeOnUpgrade() throws Exception {
+ install(APK_LOCATION_22);
+
+ install(APK_LOCATION_28);
+
+ assertFalse(isGranted(APP_PKG, ACCESS_COARSE_LOCATION));
+ assertFalse(isGranted(APP_PKG, ACCESS_BACKGROUND_LOCATION));
+ assertEquals(0,getPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION)
+ & FLAG_PERMISSION_REVOKED_COMPAT);
+ assertEquals(0,getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION)
+ & FLAG_PERMISSION_REVOKED_COMPAT);
+ }
+
+ @AsbSecurityTest(cveBugId = 283006437)
+ @Test
+ public void nonRuntimePermissionFlagsPreservedAfterReinstall() throws Exception {
+ install(APK_SYSTEM_ALERT_WINDOW_23);
+
+ int flags = FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_GRANTED_BY_ROLE;
+ setPermissionFlags(APP_SYSTEM_ALERT_WINDOW_PKG, SYSTEM_ALERT_WINDOW, flags, flags);
+ assertEquals(flags, getAllPermissionFlags(APP_SYSTEM_ALERT_WINDOW_PKG, SYSTEM_ALERT_WINDOW)
+ & flags);
+
+ install(APK_SYSTEM_ALERT_WINDOW_23);
+
+ assertEquals(flags, getAllPermissionFlags(APP_SYSTEM_ALERT_WINDOW_PKG, SYSTEM_ALERT_WINDOW)
+ & flags);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionGroupChange.java b/tests/cts/permission/src/android/permission/cts/PermissionGroupChange.java
new file mode 100644
index 000000000..46fe167c0
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionGroupChange.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import android.widget.ScrollView;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class PermissionGroupChange {
+ private static final String APP_PKG_NAME = "android.permission.cts.appthatrequestpermission";
+ private static final long EXPECTED_BEHAVIOR_TIMEOUT_SEC = 15;
+ private static final long UNEXPECTED_BEHAVIOR_TIMEOUT_SEC = 2;
+
+ private Context mContext;
+ private UiDevice mUiDevice;
+ private String mAllowButtonText = null;
+
+ @Before
+ public void setContextAndUiDevice() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ }
+
+ @Before
+ public void uninstallAndWakeUpScreen() {
+ runShellCommand("pm uninstall " + APP_PKG_NAME);
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+ }
+
+ /**
+ * Retry for a time until the runnable stops throwing.
+ *
+ * @param runnable The condition to execute
+ * @param timeoutSec The time to try
+ */
+ private void eventually(ThrowingRunnable runnable, long timeoutSec) throws Throwable {
+ long startTime = System.nanoTime();
+ while (true) {
+ try {
+ runnable.run();
+ return;
+ } catch (Throwable t) {
+ if (System.nanoTime() - startTime < TimeUnit.SECONDS.toNanos(timeoutSec)) {
+ Thread.sleep(100);
+ continue;
+ }
+
+ throw t;
+ }
+ }
+ }
+
+
+ private void scrollToBottomIfWatch() throws Exception {
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ UiScrollable scrollable = new UiScrollable(
+ new UiSelector().className(ScrollView.class));
+ if (scrollable.exists()) {
+ scrollable.flingToEnd(10);
+ }
+ }
+ }
+
+ protected void clickAllowButton() throws Exception {
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ if (mAllowButtonText == null) {
+ mAllowButtonText = getPermissionControllerString("grant_dialog_button_allow");
+ }
+ mUiDevice.findObject(By.text(Pattern.compile(Pattern.quote(mAllowButtonText),
+ Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE))).click();
+ } else {
+ mUiDevice.findObject(By.res(
+ "com.android.permissioncontroller:id/permission_allow_button")).click();
+ }
+ }
+
+ private void grantPermissionViaUi() throws Throwable {
+ eventually(() -> {
+ scrollToBottomIfWatch();
+ clickAllowButton();
+ }, EXPECTED_BEHAVIOR_TIMEOUT_SEC);
+ }
+
+ private void waitUntilPermissionGranted(String permName, long timeoutSec) throws Throwable {
+ eventually(() -> {
+ PackageInfo appInfo = mContext.getPackageManager().getPackageInfo(APP_PKG_NAME,
+ GET_PERMISSIONS);
+
+ for (int i = 0; i < appInfo.requestedPermissions.length; i++) {
+ if (appInfo.requestedPermissions[i].equals(permName)
+ && ((appInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
+ != 0)) {
+ return;
+ }
+ }
+
+ fail(permName + " not granted");
+ }, timeoutSec);
+ }
+
+ private void installApp(String apk) {
+ String installResult = SystemUtil.runShellCommandOrThrow(
+ "pm install -r /data/local/tmp/cts-permission/" + apk + ".apk");
+ assertEquals("Success", installResult.trim());
+ }
+
+ /**
+ * Start the app. The app will request the permissions.
+ */
+ private void startApp() {
+ Intent startApp = new Intent();
+ startApp.setComponent(new ComponentName(APP_PKG_NAME, APP_PKG_NAME + ".RequestPermission"));
+ startApp.setFlags(FLAG_ACTIVITY_NEW_TASK);
+
+ mContext.startActivity(startApp);
+ }
+
+ @After
+ public void uninstallTestApp() {
+ runShellCommand("pm uninstall android.permission.cts.appthatrequestpermission");
+ }
+
+ @Test
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 72710897)
+ public void permissionGroupShouldNotBeAutoGrantedIfNewMember() throws Throwable {
+ installApp("CtsAppThatRequestsPermissionAandB");
+
+ startApp();
+ grantPermissionViaUi();
+ waitUntilPermissionGranted("android.permission.cts.appthatrequestpermission.A",
+ EXPECTED_BEHAVIOR_TIMEOUT_SEC);
+
+ // Update app which changes the permission group of "android.permission.cts
+ // .appthatrequestpermission.A" to the same as "android.permission.cts.C"
+ installApp("CtsAppThatRequestsPermissionAandC");
+
+ startApp();
+ try {
+ // The permission should not be auto-granted
+ waitUntilPermissionGranted("android.permission.cts.C", UNEXPECTED_BEHAVIOR_TIMEOUT_SEC);
+ fail("android.permission.cts.C was auto-granted");
+ } catch (Throwable expected) {
+ assertEquals("android.permission.cts.C not granted", expected.getMessage());
+ }
+ }
+
+ private String getPermissionControllerString(String res)
+ throws PackageManager.NameNotFoundException {
+ Resources permissionControllerResources = mContext.createPackageContext(
+ mContext.getPackageManager().getPermissionControllerPackageName(), 0)
+ .getResources();
+ return permissionControllerResources.getString(permissionControllerResources
+ .getIdentifier(res, "string", "com.android.permissioncontroller"));
+ }
+
+ private interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionManagerNativeJniTest.java b/tests/cts/permission/src/android/permission/cts/PermissionManagerNativeJniTest.java
new file mode 100644
index 000000000..868b3d1fc
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionManagerNativeJniTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import org.junit.runner.RunWith;
+import com.android.gtestrunner.GtestRunner;
+import com.android.gtestrunner.TargetLibrary;
+
+@RunWith(GtestRunner.class)
+@TargetLibrary("permissionmanager_native_test")
+public class PermissionManagerNativeJniTest {}
+
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionManagerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionManagerTest.java
new file mode 100644
index 000000000..6fa940aa0
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionManagerTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.permission.PermissionManager;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test {@link PermissionManager}
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot talk to permission manager")
+public class PermissionManagerTest {
+ private final Context mContext = InstrumentationRegistry.getTargetContext();
+
+ @Test
+ public void testRuntimePermissionsVersion() throws Exception {
+ final PermissionManager permissionManager =
+ mContext.getSystemService(PermissionManager.class);
+ final int version = callWithShellPermissionIdentity(() ->
+ permissionManager.getRuntimePermissionsVersion());
+ assertThat(version).isAtLeast(0);
+ runWithShellPermissionIdentity(() ->
+ permissionManager.setRuntimePermissionsVersion(version));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionStubActivity.java b/tests/cts/permission/src/android/permission/cts/PermissionStubActivity.java
new file mode 100644
index 000000000..dd611777c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionStubActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.os.Bundle;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ListView;
+
+/**
+ * A minimal application for Window test.
+ */
+public class PermissionStubActivity extends Activity {
+ private ListView mListView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mListView = new ListView(this);
+ mListView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+
+ setContentView(mListView);
+ }
+
+ public Dialog getDialog() {
+ return new AlertDialog.Builder(PermissionStubActivity.this).create();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java
new file mode 100644
index 000000000..5eee04e61
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.OnPermissionsChangedListener;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.annotation.NonNull;
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@AppModeFull(reason = "Instant apps cannot access properties of other apps")
+@RunWith(AndroidJUnit4ClassRunner.class)
+public class PermissionUpdateListenerTest {
+ private static final String APK =
+ "/data/local/tmp/cts-permission/"
+ + "CtsAppThatRequestsCalendarContactsBodySensorCustomPermission.apk";
+ private static final String PACKAGE_NAME =
+ "android.permission.cts.appthatrequestcustompermission";
+ private static final String PERMISSION_NAME = "android.permission.READ_CONTACTS";
+ private static final int TIMEOUT = 30000;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+ private static final PackageManager sPm = sContext.getPackageManager();
+ private static int sUid;
+
+ @BeforeClass
+ public static void installApp() throws PackageManager.NameNotFoundException {
+ runShellCommandOrThrow("pm install -r " + APK);
+ sUid = sPm.getPackageUid(PACKAGE_NAME, 0);
+ }
+
+ @AfterClass
+ public static void unInstallApp() {
+ runShellCommand("pm uninstall " + PACKAGE_NAME);
+ }
+
+ private class LatchWithPermissionsChangedListener extends CountDownLatch
+ implements OnPermissionsChangedListener {
+
+ LatchWithPermissionsChangedListener() {
+ super(1);
+ }
+
+ public void onPermissionsChanged(int uid) {
+ if (uid == sUid) {
+ countDown();
+ }
+ }
+ }
+
+ private void waitForLatchAndRemoveListener(@NonNull LatchWithPermissionsChangedListener latch)
+ throws Exception {
+ latch.await(TIMEOUT, TimeUnit.MILLISECONDS);
+ runWithShellPermissionIdentity(() -> sPm.removeOnPermissionsChangeListener(latch));
+ assertThat(latch.getCount()).isEqualTo((long) 0);
+ }
+
+ @Test
+ public void grantNotifiesListener() throws Exception {
+ LatchWithPermissionsChangedListener listenerCalled =
+ new LatchWithPermissionsChangedListener();
+
+ runWithShellPermissionIdentity(() -> {
+ sPm.revokeRuntimePermission(PACKAGE_NAME, PERMISSION_NAME, sContext.getUser());
+ sPm.addOnPermissionsChangeListener(listenerCalled);
+ sPm.grantRuntimePermission(PACKAGE_NAME, PERMISSION_NAME, sContext.getUser());
+ });
+ waitForLatchAndRemoveListener(listenerCalled);
+ }
+
+ @Test
+ public void revokeNotifiesListener() throws Exception {
+ LatchWithPermissionsChangedListener listenerCalled =
+ new LatchWithPermissionsChangedListener();
+
+ runWithShellPermissionIdentity(() -> {
+ sPm.grantRuntimePermission(PACKAGE_NAME, PERMISSION_NAME, sContext.getUser());
+ sPm.addOnPermissionsChangeListener(listenerCalled);
+ sPm.revokeRuntimePermission(PACKAGE_NAME, PERMISSION_NAME, sContext.getUser());
+ });
+ waitForLatchAndRemoveListener(listenerCalled);
+ }
+
+ @Test
+ public void updateFlagsNotifiesListener() throws Exception {
+ LatchWithPermissionsChangedListener listenerCalled =
+ new LatchWithPermissionsChangedListener();
+
+ runWithShellPermissionIdentity(() -> {
+ sPm.addOnPermissionsChangeListener(listenerCalled);
+ int flag = PackageManager.FLAG_PERMISSION_USER_SET;
+ sPm.updatePermissionFlags(PERMISSION_NAME, PACKAGE_NAME, flag, flag,
+ sContext.getUser());
+ });
+ waitForLatchAndRemoveListener(listenerCalled);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt b/tests/cts/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt
new file mode 100644
index 000000000..7f84722f5
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PlatformPermissionGroupMappingTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.permission.cts
+
+import android.os.Build
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import org.junit.Test
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+class PlatformPermissionGroupMappingTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.context
+ private val packageManager = context.packageManager
+
+ @Test
+ fun platformPermissionHasPermissionGroup() {
+ val future = CompletableFuture<String>()
+ packageManager.getGroupOfPlatformPermission(
+ android.Manifest.permission.READ_CALENDAR, context.mainExecutor
+ ) { future.complete(it) }
+ val permissionGroupName = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ assertThat(permissionGroupName).isEqualTo(android.Manifest.permission_group.CALENDAR)
+ }
+
+ @Test
+ fun platformPermissionGroupHasPermission() {
+ val future = CompletableFuture<List<String>>()
+ packageManager.getPlatformPermissionsForGroup(
+ android.Manifest.permission_group.CALENDAR, context.mainExecutor
+ ) { future.complete(it) }
+ val permissionNames = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ assertThat(permissionNames).contains(android.Manifest.permission.READ_CALENDAR)
+ }
+
+ companion object {
+ private const val TIMEOUT_MILLIS = 15 * 1000L
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/PowerManagerServicePermissionTest.java b/tests/cts/permission/src/android/permission/cts/PowerManagerServicePermissionTest.java
new file mode 100644
index 000000000..b842cc0cf
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/PowerManagerServicePermissionTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import android.os.PowerManager;
+import android.test.AndroidTestCase;
+
+import java.time.Duration;
+
+public class PowerManagerServicePermissionTest extends AndroidTestCase {
+
+ public void testSetBatterySaver_requiresPermissions() {
+ PowerManager manager = getContext().getSystemService(PowerManager.class);
+ boolean batterySaverOn = manager.isPowerSaveMode();
+
+ try {
+ manager.setPowerSaveModeEnabled(!batterySaverOn);
+ fail("Toggling battery saver requires POWER_SAVER or DEVICE_POWER permission");
+ } catch (SecurityException e) {
+ // Expected Exception
+ }
+ }
+
+ public void testSetDynamicPowerSavings_requiresPermissions() {
+ try {
+ PowerManager manager = getContext().getSystemService(PowerManager.class);
+ manager.setDynamicPowerSaveHint(true, 0);
+ fail("Updating the dynamic power savings state requires the POWER_SAVER permission");
+ } catch (SecurityException e) {
+ // Expected Exception
+ }
+ }
+
+ public void testSetBatteryDischargePrediction_requiresPermissions() {
+ try {
+ PowerManager manager = getContext().getSystemService(PowerManager.class);
+ manager.setBatteryDischargePrediction(Duration.ofMillis(1000), false);
+ fail("Updating the discharge prediction requires the DEVICE_POWER"
+ + " or BATTERY_PREDICTION permission");
+ } catch (SecurityException e) {
+ // Expected Exception
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java b/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java
new file mode 100644
index 000000000..9f5a813d1
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ProviderPermissionTest.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE;
+import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
+
+import android.app.UiAutomation;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
+import android.provider.CallLog;
+import android.provider.Contacts;
+import android.provider.ContactsContract;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Tests Permissions related to reading from and writing to providers
+ */
+@MediumTest
+public class ProviderPermissionTest extends AndroidTestCase {
+
+ private static final String TAG = ProviderPermissionTest.class.getSimpleName();
+
+ private static final List<Uri> CONTACT_URIS = List.of(
+ Contacts.People.CONTENT_URI, // Deprecated.
+ ContactsContract.Contacts.CONTENT_FILTER_URI,
+ ContactsContract.Contacts.CONTENT_GROUP_URI,
+ ContactsContract.Contacts.CONTENT_LOOKUP_URI,
+ ContactsContract.CommonDataKinds.Email.CONTENT_URI,
+ ContactsContract.CommonDataKinds.Email.CONTENT_FILTER_URI,
+ ContactsContract.Directory.CONTENT_URI,
+ ContactsContract.Directory.ENTERPRISE_CONTENT_URI,
+ ContactsContract.Profile.CONTENT_URI);
+
+ /**
+ * Verify that reading contacts requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#READ_CONTACTS}
+ */
+ public void testReadContacts() {
+ for (Uri uri : CONTACT_URIS) {
+ Log.d(TAG, "Checking contacts URI " + uri);
+ assertReadingContentUriRequiresPermission(uri,
+ android.Manifest.permission.READ_CONTACTS);
+ }
+ }
+
+ /**
+ * Verify that writing contacts requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#WRITE_CONTACTS}
+ */
+ public void testWriteContacts() {
+ assertWritingContentUriRequiresPermission(Contacts.People.CONTENT_URI,
+ android.Manifest.permission.WRITE_CONTACTS);
+ }
+
+ /**
+ * Verify that reading call logs requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#READ_CALL_LOG}
+ */
+ @AppModeFull
+ public void testReadCallLog() {
+ assertReadingContentUriRequiresPermission(CallLog.CONTENT_URI,
+ android.Manifest.permission.READ_CALL_LOG);
+ }
+
+ /**
+ * Verify that writing call logs requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#WRITE_CALL_LOG}
+ */
+ @AppModeFull
+ public void testWriteCallLog() {
+ assertWritingContentUriRequiresPermission(CallLog.CONTENT_URI,
+ android.Manifest.permission.WRITE_CALL_LOG);
+ }
+
+ /**
+ * Verify that reading from call-log (a content provider that is not accessible to instant apps)
+ * returns null
+ */
+ @AppModeInstant
+ public void testReadCallLogInstant() {
+ assertNull(getContext().getContentResolver().query(CallLog.CONTENT_URI, null, null, null,
+ null));
+ }
+
+ /**
+ * Verify that writing to call-log (a content provider that is not accessible to instant apps)
+ * yields an IAE.
+ */
+ @AppModeInstant
+ public void testWriteCallLogInstant() {
+ try {
+ getContext().getContentResolver().insert(CallLog.CONTENT_URI, new ContentValues());
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Verify that reading already received SMS messages requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#READ_SMS}
+ *
+ * <p>Note: The WRITE_SMS permission has been removed.
+ */
+ @AppModeFull
+ public void testReadSms() {
+ if (!mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ assertReadingContentUriRequiresPermission(Telephony.Sms.CONTENT_URI,
+ android.Manifest.permission.READ_SMS);
+ }
+
+ /**
+ * Verify that reading from 'sms' (a content provider that is not accessible to instant apps)
+ * returns null
+ */
+ @AppModeInstant
+ public void testReadSmsInstant() {
+ if (!mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ assertNull(getContext().getContentResolver().query(Telephony.Sms.CONTENT_URI, null, null,
+ null, null));
+ }
+
+ /**
+ * Verify that write to settings requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#WRITE_SETTINGS}
+ */
+ public void testWriteSettings() {
+ final String permission = android.Manifest.permission.WRITE_SETTINGS;
+ ContentValues value = new ContentValues();
+ value.put(Settings.System.NAME, "name");
+ value.put(Settings.System.VALUE, "value_insert");
+
+ try {
+ getContext().getContentResolver().insert(Settings.System.CONTENT_URI, value);
+ fail("expected SecurityException requiring " + permission);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ assertTrue("error message should contain \"" + permission + "\". Got: \""
+ + expected.getMessage() + "\".",
+ expected.getMessage().contains(permission));
+ }
+ }
+
+ /**
+ * Verify that the {@link android.Manifest.permission#MANAGE_DOCUMENTS}
+ * permission is only held by up to one package: whoever handles the
+ * {@link android.content.Intent#ACTION_OPEN_DOCUMENT} intent, if any.
+ * <p>
+ * No other apps should <em>ever</em> attempt to acquire this permission,
+ * since it would give those apps extremely broad access to all storage
+ * providers on the device without user involvement in the arbitration
+ * process. Apps should instead always rely on Uri permission grants for
+ * access, using
+ * {@link android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION} and related
+ * APIs.
+ */
+ public void testManageDocuments() {
+ final PackageManager pm = getContext().getPackageManager();
+
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ final ResolveInfo ri = pm.resolveActivity(intent, 0);
+
+ if (ri != null) {
+ final String validPkg = ri.activityInfo.packageName;
+
+ final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(new String[] {
+ android.Manifest.permission.MANAGE_DOCUMENTS
+ }, PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ for (PackageInfo pi : holding) {
+ if (!Objects.equals(pi.packageName, validPkg)) {
+ fail("Exactly one package (must be " + validPkg
+ + ") can request the MANAGE_DOCUMENTS permission; found package "
+ + pi.packageName + " which must be revoked for security reasons");
+ }
+ }
+ }
+ }
+
+ /**
+ * The {@link android.Manifest.permission#WRITE_MEDIA_STORAGE} permission is
+ * a very powerful permission that grants raw storage access to all devices,
+ * and as such it's only appropriate to be granted to the media stack.
+ * <p>
+ * CDD now requires that all apps requesting this permission also hold the
+ * "Storage" runtime permission, to give users visibility into the
+ * capabilities of each app, and control over those capabilities.
+ * <p>
+ * If the end user revokes the "Storage" permission from an app, but that
+ * app still has raw access to storage via {@code WRITE_MEDIA_STORAGE}, that
+ * would be a CDD violation and a privacy incident.
+ */
+ public void testWriteMediaStorage() throws Exception {
+ final UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ final PackageManager pm = getContext().getPackageManager();
+ final UserHandle userHandle = getContext().getUser();
+ final List<PackageInfo> pkgs = pm.getInstalledPackages(
+ PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_PERMISSIONS);
+ for (PackageInfo pkg : pkgs) {
+ final int appUid = userHandle.getAppId(pkg.applicationInfo.uid);
+ final boolean isSystem = appUid == android.os.Process.SYSTEM_UID;
+ final boolean hasFrontDoor = pm.getLaunchIntentForPackage(pkg.packageName) != null;
+ final boolean grantedMedia = pm.checkPermission(WRITE_MEDIA_STORAGE,
+ pkg.packageName) == PackageManager.PERMISSION_GRANTED;
+
+ if (!isSystem && hasFrontDoor && grantedMedia) {
+ final boolean requestsStorage = contains(pkg.requestedPermissions,
+ MANAGE_EXTERNAL_STORAGE);
+ if (!requestsStorage) {
+ fail("Found " + pkg.packageName + " holding WRITE_MEDIA_STORAGE permission "
+ + "without also requesting MANAGE_EXTERNAL_STORAGE; these permissions "
+ + "must be requested together");
+ }
+
+ final boolean grantedStorage = pm.checkPermission(MANAGE_EXTERNAL_STORAGE,
+ pkg.packageName) == PackageManager.PERMISSION_GRANTED;
+ if (grantedStorage) {
+ final int flags;
+ ui.adoptShellPermissionIdentity("android.permission.GET_RUNTIME_PERMISSIONS");
+ try {
+ flags = pm.getPermissionFlags(MANAGE_EXTERNAL_STORAGE, pkg.packageName,
+ android.os.Process.myUserHandle());
+ } finally {
+ ui.dropShellPermissionIdentity();
+ }
+
+ final boolean isFixed = (flags & (PackageManager.FLAG_PERMISSION_USER_FIXED
+ | PackageManager.FLAG_PERMISSION_POLICY_FIXED
+ | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) != 0;
+ if (isFixed) {
+ fail("Found " + pkg.packageName + " holding MANAGE_EXTERNAL_STORAGE in a "
+ + "fixed state; this permission must be revokable by the user");
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean contains(String[] haystack, String needle) {
+ if (haystack != null) {
+ for (String test : haystack) {
+ if (Objects.equals(test, needle)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java b/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java
new file mode 100644
index 000000000..b1d3d5afb
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RebootPermissionTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 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.permission.cts;
+
+import android.content.Intent;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify that rebooting requires Permission.
+ */
+public class RebootPermissionTest extends AndroidTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * Verify that rebooting by sending a broadcast Intent requires Permission.
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#REBOOT}.
+ */
+ @SmallTest
+ public void testBroadcastReboot() {
+ try {
+ mContext.sendBroadcast(new Intent(Intent.ACTION_REBOOT));
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RemovePermissionTest.java b/tests/cts/permission/src/android/permission/cts/RemovePermissionTest.java
new file mode 100644
index 000000000..915918f71
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RemovePermissionTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+@AppModeFull(reason = "Instant apps cannot read state of other packages.")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class RemovePermissionTest extends StsExtraBusinessLogicTestCase {
+ private static final String APP_PKG_NAME_BASE =
+ "android.permission.cts.revokepermissionwhenremoved";
+ private static final String ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".AdversarialPermissionDefinerApp";
+ private static final String VICTIM_PERMISSION_DEFINER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".VictimPermissionDefinerApp";
+ private static final String ADVERSARIAL_PERMISSION_USER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".userapp";
+ private static final String RUNTIME_PERMISSION_USER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".runtimepermissionuserapp";
+ private static final String RUNTIME_PERMISSION_DEFINER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".runtimepermissiondefinerapp";
+ private static final String INSTALL_PERMISSION_USER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".installpermissionuserapp";
+ private static final String INSTALL_PERMISSION_DEFINER_PKG_NAME =
+ APP_PKG_NAME_BASE + ".installpermissiondefinerapp";
+ private static final String INSTALL_PERMISSION_ESCALATOR_PKG_NAME =
+ APP_PKG_NAME_BASE + ".installpermissionescalatorapp";
+
+ private static final String TEST_PERMISSION =
+ "android.permission.cts.revokepermissionwhenremoved.TestPermission";
+ private static final String TEST_RUNTIME_PERMISSION =
+ APP_PKG_NAME_BASE + ".TestRuntimePermission";
+ private static final String TEST_INSTALL_PERMISSION =
+ APP_PKG_NAME_BASE + ".TestInstallPermission";
+
+ private static final String ADVERSARIAL_PERMISSION_DEFINER_APK_NAME =
+ "CtsAdversarialPermissionDefinerApp";
+ private static final String ADVERSARIAL_PERMISSION_USER_APK_NAME =
+ "CtsAdversarialPermissionUserApp";
+ private static final String VICTIM_PERMISSION_DEFINER_APK_NAME =
+ "CtsVictimPermissionDefinerApp";
+ private static final String RUNTIME_PERMISSION_DEFINER_APK_NAME =
+ "CtsRuntimePermissionDefinerApp";
+ private static final String RUNTIME_PERMISSION_USER_APK_NAME =
+ "CtsRuntimePermissionUserApp";
+ private static final String INSTALL_PERMISSION_DEFINER_APK_NAME =
+ "CtsInstallPermissionDefinerApp";
+ private static final String INSTALL_PERMISSION_USER_APK_NAME =
+ "CtsInstallPermissionUserApp";
+ private static final String INSTALL_PERMISSION_ESCALATOR_APK_NAME =
+ "CtsInstallPermissionEscalatorApp";
+
+ private Context mContext;
+ private Instrumentation mInstrumentation;
+
+ @Before
+ public void setContextAndInstrumentation() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @Before
+ public void wakeUpScreen() {
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+ }
+
+ @After
+ public void cleanUpTestApps() throws Exception {
+ uninstallApp(ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME, true);
+ uninstallApp(ADVERSARIAL_PERMISSION_USER_PKG_NAME, true);
+ uninstallApp(VICTIM_PERMISSION_DEFINER_PKG_NAME, true);
+ uninstallApp(RUNTIME_PERMISSION_DEFINER_PKG_NAME, true);
+ uninstallApp(RUNTIME_PERMISSION_USER_PKG_NAME, true);
+ uninstallApp(INSTALL_PERMISSION_USER_PKG_NAME, true);
+ uninstallApp(INSTALL_PERMISSION_DEFINER_PKG_NAME, true);
+ uninstallApp(INSTALL_PERMISSION_ESCALATOR_PKG_NAME, true);
+ Thread.sleep(5000);
+ }
+
+ private boolean permissionGranted(String pkgName, String permName)
+ throws PackageManager.NameNotFoundException {
+ PackageInfo appInfo = mContext.getPackageManager().getPackageInfo(pkgName,
+ GET_PERMISSIONS);
+
+ for (int i = 0; i < appInfo.requestedPermissions.length; i++) {
+ if (appInfo.requestedPermissions[i].equals(permName)
+ && ((appInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
+ != 0)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void installApp(String apk) throws InterruptedException {
+ String installResult = SystemUtil.runShellCommandOrThrow(
+ "pm install -r -d /data/local/tmp/cts-permission/" + apk + ".apk");
+ assertEquals("Success", installResult.trim());
+ Thread.sleep(5000);
+ }
+
+ private void uninstallApp(String pkg) throws InterruptedException {
+ uninstallApp(pkg, false);
+ }
+
+ private void uninstallApp(String pkg, boolean cleanUp) throws InterruptedException {
+ String uninstallResult = SystemUtil.runShellCommand("pm uninstall " + pkg);
+ if (!cleanUp) {
+ assertEquals("Success", uninstallResult.trim());
+ Thread.sleep(5000);
+ }
+ }
+
+ private void grantPermission(String pkg, String permission) {
+ mInstrumentation.getUiAutomation().grantRuntimePermission(
+ pkg, permission);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 67319274)
+ public void runtimePermissionShouldBeRevokedIfRemoved() throws Throwable {
+ installApp(ADVERSARIAL_PERMISSION_DEFINER_APK_NAME);
+ installApp(ADVERSARIAL_PERMISSION_USER_APK_NAME);
+
+ grantPermission(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION);
+ assertTrue(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
+
+ // Uninstall app which defines a permission with the same name as in victim app.
+ // Install the victim app.
+ uninstallApp(ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME);
+ installApp(VICTIM_PERMISSION_DEFINER_APK_NAME);
+ assertFalse(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
+ }
+
+ @Test
+ public void runtimePermissionShouldRemainGrantedAfterAppUpdate() throws Throwable {
+ installApp(RUNTIME_PERMISSION_DEFINER_APK_NAME);
+ installApp(RUNTIME_PERMISSION_USER_APK_NAME);
+
+ grantPermission(RUNTIME_PERMISSION_USER_PKG_NAME, TEST_RUNTIME_PERMISSION);
+ assertTrue(permissionGranted(RUNTIME_PERMISSION_USER_PKG_NAME, TEST_RUNTIME_PERMISSION));
+
+ // Install app which defines a permission. This is similar to update the app
+ // operation
+ installApp(RUNTIME_PERMISSION_DEFINER_APK_NAME);
+ assertTrue(permissionGranted(RUNTIME_PERMISSION_USER_PKG_NAME, TEST_RUNTIME_PERMISSION));
+ }
+
+ @Test
+ public void runtimePermissionDependencyTest() throws Throwable {
+ installApp(ADVERSARIAL_PERMISSION_USER_APK_NAME);
+ // Should fail to grant permission because its definer is not installed yet
+ try {
+ grantPermission(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION);
+ fail("Should have thrown security exception above");
+ } catch (SecurityException expected) {
+ }
+ assertFalse(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
+ // Now install the permission definer; should be able to grant permission to user package
+ installApp(ADVERSARIAL_PERMISSION_DEFINER_APK_NAME);
+ grantPermission(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION);
+ assertTrue(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
+ // Now uninstall the permission definer; the user packages' permission should be revoked
+ uninstallApp(ADVERSARIAL_PERMISSION_DEFINER_PKG_NAME);
+ assertFalse(permissionGranted(ADVERSARIAL_PERMISSION_USER_PKG_NAME, TEST_PERMISSION));
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 155648771)
+ public void installPermissionShouldBeRevokedIfRemoved() throws Throwable {
+ installApp(INSTALL_PERMISSION_DEFINER_APK_NAME);
+ installApp(INSTALL_PERMISSION_USER_APK_NAME);
+ assertTrue(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+
+ // Uninstall the app which defines the install permission, and install another app
+ // redefining it as a runtime permission.
+ uninstallApp(INSTALL_PERMISSION_DEFINER_PKG_NAME);
+ installApp(INSTALL_PERMISSION_ESCALATOR_APK_NAME);
+ assertFalse(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+ }
+
+ @Test
+ public void installPermissionShouldRemainGrantedAfterAppUpdate() throws Throwable {
+ installApp(INSTALL_PERMISSION_DEFINER_APK_NAME);
+ installApp(INSTALL_PERMISSION_USER_APK_NAME);
+ assertTrue(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+
+ // Install the app which defines the install permission again, similar to updating the app.
+ installApp(INSTALL_PERMISSION_DEFINER_APK_NAME);
+ assertTrue(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+ }
+
+ @Test
+ public void installPermissionDependencyTest() throws Throwable {
+ installApp(INSTALL_PERMISSION_USER_APK_NAME);
+ // Should not have the permission auto-granted
+ assertFalse(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+
+ // Now install the permission definer; user package should have the permission auto granted
+ installApp(INSTALL_PERMISSION_DEFINER_APK_NAME);
+ installApp(INSTALL_PERMISSION_USER_APK_NAME);
+ assertTrue(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+
+ // Now uninstall the permission definer; the user package's permission should be revoked
+ uninstallApp(INSTALL_PERMISSION_DEFINER_PKG_NAME);
+ assertFalse(permissionGranted(INSTALL_PERMISSION_USER_PKG_NAME, TEST_INSTALL_PERMISSION));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RevokePermissionTest.kt b/tests/cts/permission/src/android/permission/cts/RevokePermissionTest.kt
new file mode 100644
index 000000000..2a6642708
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RevokePermissionTest.kt
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2020 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.permission.cts
+
+import android.Manifest.permission.CAMERA
+import android.Manifest.permission.READ_CALENDAR
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import android.os.Process
+import android.platform.test.annotations.AppModeFull
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+
+class RevokePermissionTest {
+
+ private val APP_PKG_NAME = "android.permission.cts.appthatrequestcustompermission"
+ private val APK = "/data/local/tmp/cts-permission/" +
+ "CtsAppThatRequestsCalendarContactsBodySensorCustomPermission.apk"
+
+ @Before
+ fun installApp() {
+ runShellCommand("pm install -r -g $APK")
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokePermission() {
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = READ_CALENDAR,
+ isGranted = true)
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokePermissionNotRequested() {
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = CAMERA,
+ throwableType = SecurityException::class.java,
+ throwableMessages = listOf(
+ "has not requested permission",
+ "Permission $CAMERA isn't requested by package $APP_PKG_NAME"
+ ))
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokeFakePermission() {
+ val fakePermissionName = "FAKE_PERMISSION"
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = fakePermissionName,
+ throwableType = java.lang.IllegalArgumentException::class.java,
+ throwableMessages = listOf(
+ "Unknown permission: $fakePermissionName",
+ "Unknown permission $fakePermissionName"
+ ))
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokeFakePackage() {
+ val fakePackageName = "fake.package.name.which.should.not.exist"
+ assertPackageNotInstalled(fakePackageName)
+ testRevoke(
+ packageName = fakePackageName,
+ permission = READ_CALENDAR)
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokePermissionWithReason() {
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = READ_CALENDAR,
+ reason = "test reason",
+ isGranted = true)
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokePermissionNotRequestedWithReason() {
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = CAMERA,
+ reason = "test reason",
+ throwableType = SecurityException::class.java,
+ throwableMessages = listOf(
+ "has not requested permission",
+ "Permission $CAMERA isn't requested by package $APP_PKG_NAME"
+ ))
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokeFakePermissionWithReason() {
+ val fakePermissionName = "FAKE_PERMISSION"
+ testRevoke(
+ packageName = APP_PKG_NAME,
+ permission = fakePermissionName,
+ reason = "test reason",
+ throwableType = java.lang.IllegalArgumentException::class.java,
+ throwableMessages = listOf(
+ "Unknown permission: $fakePermissionName",
+ "Unknown permission $fakePermissionName"
+ ))
+ }
+
+ @Test
+ @AppModeFull(reason = "Instant apps can't revoke permissions.")
+ fun testRevokeFakePackageWithReason() {
+ val fakePackageName = "fake.package.name.which.should.not.exist"
+ assertPackageNotInstalled(fakePackageName)
+ testRevoke(
+ packageName = fakePackageName,
+ permission = READ_CALENDAR,
+ reason = "test reason")
+ }
+
+ @After
+ fun uninstallApp() {
+ runShellCommand("pm uninstall $APP_PKG_NAME")
+ }
+
+ private fun testRevoke(
+ packageName: String,
+ permission: String,
+ reason: String? = null,
+ isGranted: Boolean = false,
+ throwableType: Class<*>? = null,
+ throwableMessages: List<String> = listOf("")
+ ) {
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ val pm = context.packageManager
+
+ if (isGranted) {
+ assertEquals(PERMISSION_GRANTED, pm.checkPermission(READ_CALENDAR, APP_PKG_NAME))
+ }
+
+ runWithShellPermissionIdentity {
+ if (throwableType == null) {
+ if (reason == null) {
+ pm.revokeRuntimePermission(packageName, permission, Process.myUserHandle())
+ } else {
+ pm.revokeRuntimePermission(packageName, permission, Process.myUserHandle(),
+ reason)
+ }
+ } else {
+ try {
+ if (reason == null) {
+ pm.revokeRuntimePermission(packageName, permission, Process.myUserHandle())
+ } else {
+ pm.revokeRuntimePermission(packageName, permission, Process.myUserHandle(),
+ reason)
+ }
+ } catch (t: Throwable) {
+ if (t::class.java.name == throwableType.name &&
+ throwableMessages.any { t.message!!.contains(it) }) {
+ return@runWithShellPermissionIdentity
+ }
+ throw RuntimeException("Unexpected throwable", t)
+ }
+ throw RuntimeException("revokeRuntimePermission expected to throw.")
+ }
+ }
+ }
+
+ private fun assertPackageNotInstalled(packageName: String) {
+ val context = InstrumentationRegistry.getInstrumentation().targetContext
+ val pm = context.packageManager
+ try {
+ pm.getPackageInfo(packageName, 0)
+ throw RuntimeException("$packageName exists on this device")
+ } catch (e: PackageManager.NameNotFoundException) {
+ // Expected
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt b/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
new file mode 100644
index 000000000..9bc955de9
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.permission.cts
+
+import android.content.pm.PackageManager
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.After
+import org.junit.Assert
+import org.junit.Test
+
+private val APP_PKG_NAME = "android.permission.cts.usesystemalertwindowpermission"
+private val APK_22 = "/data/local/tmp/cts-permission/" +
+ "CtsAppThatRequestsSystemAlertWindow22.apk"
+private val APK_23 = "/data/local/tmp/cts-permission/" +
+ "CtsAppThatRequestsSystemAlertWindow23.apk"
+
+class RevokeSawPermissionTest {
+
+ fun installApp(apk: String) {
+ PermissionUtils.install(apk)
+ }
+
+ @After
+ fun uninstallApp() {
+ PermissionUtils.uninstallApp(APP_PKG_NAME)
+ }
+
+ @AsbSecurityTest(cveBugId = [221040577L])
+ @Test
+ fun testPre23AppsWithSystemAlertWindowGetDeniedOnUpgrade() {
+ installApp(APK_22)
+ assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, true)
+ installApp(APK_23)
+ assertAppHasPermission(android.Manifest.permission.SYSTEM_ALERT_WINDOW, false)
+ }
+
+ private fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) {
+ Assert.assertEquals(
+ if (expectPermission) {
+ PackageManager.PERMISSION_GRANTED
+ } else {
+ PackageManager.PERMISSION_DENIED
+ },
+ InstrumentationRegistry.getInstrumentation().getTargetContext().packageManager
+ .checkPermission(permissionName, APP_PKG_NAME)
+ )
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RevokeSelfPermissionTest.java b/tests/cts/permission/src/android/permission/cts/RevokeSelfPermissionTest.java
new file mode 100644
index 000000000..674fa2d12
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RevokeSelfPermissionTest.java
@@ -0,0 +1,361 @@
+/*
+ * 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.CAMERA;
+import static android.Manifest.permission.HIGH_SAMPLING_RATE_SENSORS;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.permission.cts.PermissionUtils.getPermissionFlags;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.setPermissionFlags;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.os.Build;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.DeviceConfig;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@AppModeFull(reason = "Null permission info in instant mode")
+public class RevokeSelfPermissionTest {
+ private static final String APP_PKG_NAME =
+ "android.permission.cts.apptotestrevokeselfpermission";
+ private static final String APK =
+ "/data/local/tmp/cts-permission/CtsAppToTestRevokeSelfPermission.apk";
+ private static final long ONE_TIME_TIMEOUT_MILLIS = 500;
+ private static final long ONE_TIME_TIMER_UPPER_GRACE_PERIOD = 5000;
+
+ private final Instrumentation mInstrumentation =
+ InstrumentationRegistry.getInstrumentation();
+ private final Context mContext = mInstrumentation.getTargetContext();
+ private final ActivityManager mActivityManager =
+ mContext.getSystemService(ActivityManager.class);
+ private final UiDevice mUiDevice = UiDevice.getInstance(mInstrumentation);
+ private String mOldOneTimePermissionTimeoutValue;
+ private String mOldScreenOffTimeoutValue;
+ private String mOldSleepTimeoutValue;
+
+ @Before
+ public void wakeUpScreen() {
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP");
+ SystemUtil.runShellCommand("input keyevent 82");
+ mOldScreenOffTimeoutValue = SystemUtil.runShellCommand(
+ "settings get system screen_off_timeout");
+ mOldSleepTimeoutValue = SystemUtil.runShellCommand("settings get secure sleep_timeout");
+ SystemUtil.runShellCommand("settings put system screen_off_timeout -1");
+ SystemUtil.runShellCommand("settings put secure sleep_timeout -1");
+ }
+
+ @Before
+ public void prepareDeviceForOneTime() {
+ runWithShellPermissionIdentity(() -> {
+ mOldOneTimePermissionTimeoutValue = DeviceConfig.getProperty("permissions",
+ "one_time_permissions_timeout_millis");
+ DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+ Long.toString(ONE_TIME_TIMEOUT_MILLIS), false);
+ });
+ }
+
+ @After
+ public void uninstallApp() {
+ runShellCommand("pm uninstall " + APP_PKG_NAME);
+ }
+
+ @After
+ public void restoreDeviceForOneTime() {
+ runWithShellPermissionIdentity(() -> {
+ DeviceConfig.setProperty("permissions", "one_time_permissions_timeout_millis",
+ mOldOneTimePermissionTimeoutValue, false);
+ });
+ SystemUtil.runShellCommand("settings put system screen_off_timeout "
+ + mOldScreenOffTimeoutValue);
+ SystemUtil.runShellCommand("settings put secure sleep_timeout " + mOldSleepTimeoutValue);
+ }
+
+ @Test
+ public void testMultiplePermissions() throws Throwable {
+ // Trying to revoke multiple permissions including some from the same permission group
+ // should work.
+ installApp();
+ String[] permissions = new String[] {ACCESS_COARSE_LOCATION, ACCESS_BACKGROUND_LOCATION,
+ CAMERA};
+ for (String permission : permissions) {
+ grantPermission(APP_PKG_NAME, permission);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, permission);
+ }
+ revokePermissions(permissions);
+ placeAppInBackground();
+ for (String permission : permissions) {
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ permission);
+ }
+ uninstallApp();
+ }
+
+ @Test
+ public void testNormalPermission() throws Throwable {
+ // Trying to revoke a normal (non-runtime) permission should not actually revoke it.
+ installApp();
+ revokePermission(HIGH_SAMPLING_RATE_SENSORS);
+ placeAppInBackground();
+ try {
+ waitUntilPermissionRevoked(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ HIGH_SAMPLING_RATE_SENSORS);
+ fail("android.permission.HIGH_SAMPLING_RATE_SENSORS was revoked");
+ } catch (Throwable expected) {
+ assertEquals(HIGH_SAMPLING_RATE_SENSORS + " not revoked",
+ expected.getMessage());
+ }
+ uninstallApp();
+ }
+
+ @Test
+ public void testKillTriggersRevocation() throws Throwable {
+ // Killing the process should start the revocation right away
+ installApp();
+ grantPermission(APP_PKG_NAME, ACCESS_FINE_LOCATION);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_FINE_LOCATION);
+ revokePermission(ACCESS_FINE_LOCATION);
+ killApp();
+ assertDenied(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_FINE_LOCATION);
+ uninstallApp();
+ }
+
+ @Test
+ public void testNoRevocationWhileForeground() throws Throwable {
+ // Even after calling revokeSelfPermissionOnKill, the permission should stay granted while
+ // the package is in the foreground.
+ installApp();
+ grantPermission(APP_PKG_NAME, ACCESS_FINE_LOCATION);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_FINE_LOCATION);
+ revokePermission(ACCESS_FINE_LOCATION);
+ keepAppInForeground(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD);
+ try {
+ waitUntilPermissionRevoked(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_FINE_LOCATION);
+ fail("android.permission.ACCESS_FINE_LOCATION was revoked");
+ } catch (Throwable expected) {
+ assertEquals(ACCESS_FINE_LOCATION + " not revoked",
+ expected.getMessage());
+ }
+ uninstallApp();
+ }
+
+ @Test
+ public void testRevokeLocationPermission() throws Throwable {
+ // Test behavior specific to location group: revoking fine location should not revoke coarse
+ // location, and background location should not be revoked as long as a foreground
+ // permission is still granted
+ installApp();
+ grantPermission(APP_PKG_NAME, ACCESS_COARSE_LOCATION);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG_NAME, ACCESS_FINE_LOCATION);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_FINE_LOCATION);
+ grantPermission(APP_PKG_NAME, ACCESS_BACKGROUND_LOCATION);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_BACKGROUND_LOCATION);
+ revokePermission(ACCESS_BACKGROUND_LOCATION);
+ killApp();
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_BACKGROUND_LOCATION);
+ assertGranted(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_COARSE_LOCATION);
+ assertGranted(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_FINE_LOCATION);
+ grantPermission(APP_PKG_NAME, ACCESS_BACKGROUND_LOCATION);
+ setPermissionFlags(APP_PKG_NAME, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_ONE_TIME, 0);
+ assertGranted(ONE_TIME_TIMER_UPPER_GRACE_PERIOD, ACCESS_BACKGROUND_LOCATION);
+ revokePermission(ACCESS_FINE_LOCATION);
+ killApp();
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_FINE_LOCATION);
+ assertGranted(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_COARSE_LOCATION);
+ assertGranted(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_BACKGROUND_LOCATION);
+ revokePermission(ACCESS_COARSE_LOCATION);
+ killApp();
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_COARSE_LOCATION);
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_BACKGROUND_LOCATION);
+ uninstallApp();
+ }
+
+ @Test
+ public void testNoRepromptWhenUserFixed() throws Throwable {
+ // If a permission has been USER_FIXED to not granted, then revoking the permission group
+ // should leave the USER_FIXED flag.
+ installApp();
+ grantPermission(APP_PKG_NAME, ACCESS_FINE_LOCATION);
+ setPermissionFlags(APP_PKG_NAME, ACCESS_BACKGROUND_LOCATION, FLAG_PERMISSION_USER_FIXED,
+ FLAG_PERMISSION_USER_FIXED);
+ revokePermission(ACCESS_FINE_LOCATION);
+ placeAppInBackground();
+ assertDenied(ONE_TIME_TIMEOUT_MILLIS + ONE_TIME_TIMER_UPPER_GRACE_PERIOD,
+ ACCESS_FINE_LOCATION);
+ int flags = getPermissionFlags(APP_PKG_NAME, ACCESS_BACKGROUND_LOCATION);
+ assertEquals(FLAG_PERMISSION_USER_FIXED, flags & FLAG_PERMISSION_USER_FIXED);
+ uninstallApp();
+ }
+
+
+ private void installApp() {
+ runShellCommandOrThrow("pm install -r " + APK);
+ }
+
+ private void keepAppInForeground(long timeoutMillis) {
+ new Thread(() -> {
+ long start = System.currentTimeMillis();
+ while (System.currentTimeMillis() < start + timeoutMillis) {
+ runWithShellPermissionIdentity(() -> {
+ if (mActivityManager.getPackageImportance(APP_PKG_NAME)
+ > IMPORTANCE_FOREGROUND) {
+ runShellCommand("am start-activity -W -n " + APP_PKG_NAME
+ + "/.RevokePermission");
+ }
+ });
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ }
+ }).start();
+ }
+
+ private void placeAppInBackground() {
+ boolean[] hasExited = {false};
+ try {
+ new Thread(() -> {
+ while (!hasExited[0]) {
+ mUiDevice.pressHome();
+ mUiDevice.pressBack();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }).start();
+ eventually(() -> {
+ runWithShellPermissionIdentity(() -> {
+ if (mActivityManager.getPackageImportance(APP_PKG_NAME)
+ <= IMPORTANCE_FOREGROUND) {
+ throw new AssertionError("Unable to exit application");
+ }
+ });
+ });
+ } finally {
+ hasExited[0] = true;
+ }
+ }
+
+ /**
+ * Start the app. The app will revoke the permission.
+ */
+ private void revokePermission(String permName) {
+ revokePermissions(new String[] { permName });
+ }
+
+ private void revokePermissions(String[] permissions) {
+ runShellCommand("am start-activity -W -n " + APP_PKG_NAME + "/.RevokePermission"
+ + " --esa permissions " + String.join(",", permissions));
+ PackageManager pkgMgr = mContext.getPackageManager();
+ eventually(() -> runWithShellPermissionIdentity(() -> {
+ for (int i = 0; i < permissions.length; i++) {
+ if ((pkgMgr.getPermissionInfo(permissions[i], 0).getProtection()
+ & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
+ int permissionFlags = pkgMgr.getPermissionFlags(permissions[i], APP_PKG_NAME,
+ Process.myUserHandle());
+ Assert.assertTrue((permissionFlags & FLAG_PERMISSION_ONE_TIME) != 0);
+ }
+ }
+ }));
+ }
+
+ private void killApp() {
+ runShellCommand("am force-stop " + APP_PKG_NAME);
+ }
+
+ private void assertGrantedState(String s, String permissionName, int permissionGranted,
+ long timeoutMillis) {
+ eventually(() -> Assert.assertEquals(s, permissionGranted,
+ mContext.getPackageManager().checkPermission(permissionName, APP_PKG_NAME)),
+ timeoutMillis);
+ }
+
+ private void assertGranted(long timeoutMillis, String permissionName) {
+ assertGrantedState("Permission was never granted", permissionName,
+ PackageManager.PERMISSION_GRANTED, timeoutMillis);
+ }
+
+ private void assertDenied(long timeoutMillis, String permissionName) {
+ assertGrantedState("Permission was never revoked", permissionName,
+ PackageManager.PERMISSION_DENIED, timeoutMillis);
+ }
+
+ private void waitUntilPermissionRevoked(long timeoutMillis, String permName) throws Throwable {
+ try {
+ eventually(() -> {
+ PackageInfo appInfo = mContext.getPackageManager().getPackageInfo(APP_PKG_NAME,
+ GET_PERMISSIONS);
+
+ for (int i = 0; i < appInfo.requestedPermissions.length; i++) {
+ if (appInfo.requestedPermissions[i].equals(permName)
+ && (
+ (appInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
+ == 0)) {
+ return;
+ }
+ }
+
+ fail(permName + " not revoked");
+ }, timeoutMillis);
+ } catch (RuntimeException e) {
+ throw e.getCause();
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/RuntimePermissionPresentationInfoTest.java b/tests/cts/permission/src/android/permission/cts/RuntimePermissionPresentationInfoTest.java
new file mode 100644
index 000000000..9294c0aff
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/RuntimePermissionPresentationInfoTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 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.permission.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.permission.RuntimePermissionPresentationInfo;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test {@link RuntimePermissionPresentationInfoTest}
+ */
+@RunWith(AndroidJUnit4.class)
+public class RuntimePermissionPresentationInfoTest {
+ @Test
+ public void runtimePermissionLabelSet() {
+ assertThat(new RuntimePermissionPresentationInfo("test", true,
+ true).getLabel()).isEqualTo("test");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void runtimePermissionLabelSetNull() {
+ RuntimePermissionPresentationInfo info = new RuntimePermissionPresentationInfo(null, true,
+ true);
+ }
+
+ @Test
+ public void runtimePermissionGrantedCanBeTrue() {
+ assertThat(new RuntimePermissionPresentationInfo("", true, true).isGranted()).isTrue();
+ }
+
+ @Test
+ public void runtimePermissionGrantedCanBeFalse() {
+ assertThat(new RuntimePermissionPresentationInfo("", false, true).isGranted()).isFalse();
+ }
+
+ @Test
+ public void runtimePermissionStandardCanBeTrue() {
+ assertThat(new RuntimePermissionPresentationInfo("", true, true).isStandard()).isTrue();
+ }
+
+ @Test
+ public void runtimePermissionStandardCanBeFalse() {
+ assertThat(new RuntimePermissionPresentationInfo("", true, false).isStandard()).isFalse();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SafetyCenterUtils.kt b/tests/cts/permission/src/android/permission/cts/SafetyCenterUtils.kt
new file mode 100644
index 000000000..c10c0bdbe
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SafetyCenterUtils.kt
@@ -0,0 +1,151 @@
+/*
+ * 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.permission.cts
+
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.content.Context
+import android.content.Intent
+import android.content.res.Resources
+import android.os.Build
+import android.os.UserHandle
+import android.provider.DeviceConfig
+import android.safetycenter.SafetyCenterIssue
+import android.safetycenter.SafetyCenterManager
+import androidx.annotation.RequiresApi
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
+import com.android.safetycenter.internaldata.SafetyCenterIds
+import com.android.safetycenter.internaldata.SafetyCenterIssueId
+import com.android.safetycenter.internaldata.SafetyCenterIssueKey
+import org.junit.Assert
+
+object SafetyCenterUtils {
+ /** Name of the flag that determines whether SafetyCenter is enabled. */
+ const val PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+
+ /** Returns whether the device supports Safety Center. */
+ @JvmStatic
+ fun deviceSupportsSafetyCenter(context: Context): Boolean {
+ return context.resources.getBoolean(
+ Resources.getSystem().getIdentifier("config_enableSafetyCenter", "bool", "android"))
+ }
+
+ /** Enabled or disable Safety Center */
+ @JvmStatic
+ fun setSafetyCenterEnabled(enabled: Boolean) {
+ setDeviceConfigPrivacyProperty(PROPERTY_SAFETY_CENTER_ENABLED, enabled.toString())
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @JvmStatic
+ fun startSafetyCenterActivity(context: Context) {
+ context.startActivity(
+ Intent(Intent.ACTION_SAFETY_CENTER)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
+ }
+
+ @JvmStatic
+ fun assertSafetyCenterStarted() {
+ // CollapsingToolbar title can't be found by text, so using description instead.
+ waitFindObject(By.desc("Security & privacy"))
+ }
+
+ @JvmStatic
+ fun setDeviceConfigPrivacyProperty(
+ propertyName: String,
+ value: String,
+ uiAutomation: UiAutomation = instrumentation.uiAutomation
+ ) {
+ runWithShellPermissionIdentity(uiAutomation) {
+ val valueWasSet =
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ /* name = */ propertyName,
+ /* value = */ value,
+ /* makeDefault = */ false)
+ check(valueWasSet) { "Could not set $propertyName to $value" }
+ }
+ }
+
+ @JvmStatic
+ fun deleteDeviceConfigPrivacyProperty(
+ propertyName: String,
+ uiAutomation: UiAutomation = instrumentation.uiAutomation
+ ) {
+ runWithShellPermissionIdentity(uiAutomation) {
+ DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_PRIVACY, propertyName)
+ }
+ }
+
+ @JvmStatic
+ private fun getSafetyCenterIssues(
+ automation: UiAutomation = instrumentation.uiAutomation
+ ): List<SafetyCenterIssue> {
+ val safetyCenterManager =
+ instrumentation.targetContext.getSystemService(SafetyCenterManager::class.java)
+ val issues = ArrayList<SafetyCenterIssue>()
+ runWithShellPermissionIdentity(automation) {
+ val safetyCenterData = safetyCenterManager!!.safetyCenterData
+ issues.addAll(safetyCenterData.issues)
+ }
+ return issues
+ }
+
+ @JvmStatic
+ fun assertSafetyCenterIssueExist(
+ sourceId: String,
+ issueId: String,
+ issueTypeId: String,
+ automation: UiAutomation = instrumentation.uiAutomation
+ ) {
+ val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId)
+ Assert.assertTrue(
+ "Expect issues in safety center",
+ getSafetyCenterIssues(automation).any { safetyCenterIssueId == it.id })
+ }
+
+ @JvmStatic
+ fun assertSafetyCenterIssueDoesNotExist(
+ sourceId: String,
+ issueId: String,
+ issueTypeId: String,
+ automation: UiAutomation = instrumentation.uiAutomation
+ ) {
+ val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId)
+ Assert.assertTrue(
+ "Expect no issue in safety center",
+ getSafetyCenterIssues(automation).none { safetyCenterIssueId == it.id })
+ }
+
+ private fun safetyCenterIssueId(sourceId: String, sourceIssueId: String, issueTypeId: String) =
+ SafetyCenterIds.encodeToString(
+ SafetyCenterIssueId.newBuilder()
+ .setSafetyCenterIssueKey(
+ SafetyCenterIssueKey.newBuilder()
+ .setSafetySourceId(sourceId)
+ .setSafetySourceIssueId(sourceIssueId)
+ .setUserId(UserHandle.myUserId())
+ .build())
+ .setIssueTypeId(issueTypeId)
+ .build())
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SdkSandboxPermissionTest.java b/tests/cts/permission/src/android/permission/cts/SdkSandboxPermissionTest.java
new file mode 100644
index 000000000..88fcaec45
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SdkSandboxPermissionTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.permission.cts;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Process;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.SdkSuppress;
+import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for permission handling for sdk sandbox uid range.
+ */
+@AppModeFull(reason = "Instant apps can't access PermissionManager")
+@RunWith(AndroidJUnit4ClassRunner.class)
+public class SdkSandboxPermissionTest {
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ public void testSdkSandboxHasInternetPermission() throws Exception {
+ final Context ctx = getInstrumentation().getContext();
+ int ret = ctx.checkPermission(
+ Manifest.permission.INTERNET,
+ /* pid= */ -1 /* invalid pid */,
+ Process.toSdkSandboxUid(19999));
+ assertThat(ret).isEqualTo(PackageManager.PERMISSION_GRANTED);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ public void testSdkSandboxDoesNotHaveFineLocationPermission() throws Exception {
+ final Context ctx = getInstrumentation().getContext();
+ int ret = ctx.checkPermission(
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ /* pid= */ -1 /* invalid pid */,
+ Process.toSdkSandboxUid(19999));
+ assertThat(ret).isEqualTo(PackageManager.PERMISSION_DENIED);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SecureElementPermissionTest.java b/tests/cts/permission/src/android/permission/cts/SecureElementPermissionTest.java
new file mode 100644
index 000000000..1f04b1ccf
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SecureElementPermissionTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static org.junit.Assert.fail;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Process;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+@RunWith(JUnit4.class)
+public final class SecureElementPermissionTest {
+ // Needed because SECURE_ELEMENT_PRIVILEGED_PERMISSION is a systemapi
+ public static final String SECURE_ELEMENT_PRIVILEGED_PERMISSION =
+ "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
+
+ @Test
+ public void testSecureElementPrivilegedPermission() {
+ PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+
+ List<Integer> specialUids = Arrays.asList(Process.SYSTEM_UID, Process.PHONE_UID);
+
+ List<PackageInfo> holding = pm.getPackagesHoldingPermissions(
+ new String[] { SECURE_ELEMENT_PRIVILEGED_PERMISSION },
+ PackageManager.MATCH_DISABLED_COMPONENTS);
+
+ List<Integer> nonSpecialPackages = holding.stream()
+ .map(pi -> {
+ try {
+ return pm.getPackageUid(pi.packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return Process.INVALID_UID;
+ }
+ })
+ .filter(uid -> !specialUids.contains(uid))
+ .collect(Collectors.toList());
+
+ if (nonSpecialPackages.size() > 1) {
+ fail("Only one app on the device is allowed to hold the " +
+ "SECURE_ELEMENT_PRIVILEGED_OPERATION permission.");
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ServicePermissionTest.java b/tests/cts/permission/src/android/permission/cts/ServicePermissionTest.java
new file mode 100644
index 000000000..6c10f1d31
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ServicePermissionTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 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.permission.cts;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The security designs of many system features require that a special
+ * permission is only ever granted to the core system (typically
+ * {@code system_server}), since it's the only process that should be binding
+ * into sensitive app code.
+ * <p>
+ * No apps outside the {@code system_server} should <em>ever</em> attempt to
+ * acquire these permissions.
+ */
+public class ServicePermissionTest extends AndroidTestCase {
+ public static String[] sServicePermissions = {
+ android.Manifest.permission.ACCOUNT_MANAGER,
+ android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE,
+ android.Manifest.permission.BIND_AUTOFILL_SERVICE,
+ android.Manifest.permission.BIND_CHOOSER_TARGET_SERVICE,
+ android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE,
+ // android.Manifest.permission.BIND_DEVICE_ADMIN,
+ android.Manifest.permission.BIND_DREAM_SERVICE,
+ android.Manifest.permission.BIND_INPUT_METHOD,
+ android.Manifest.permission.BIND_MIDI_DEVICE_SERVICE,
+ // android.Manifest.permission.BIND_NFC_SERVICE,
+ android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE,
+ android.Manifest.permission.BIND_PRINT_SERVICE,
+ // android.Manifest.permission.BIND_QUICK_SETTINGS_TILE,
+ android.Manifest.permission.BIND_TEXT_SERVICE,
+ android.Manifest.permission.BIND_VOICE_INTERACTION,
+ android.Manifest.permission.BIND_VPN_SERVICE,
+ android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
+ };
+
+ public void testServicePermissions() {
+ final PackageManager pm = getContext().getPackageManager();
+
+ final List<String> failures = new ArrayList<>();
+ for (String perm : sServicePermissions) {
+ final List<PackageInfo> holding = pm.getPackagesHoldingPermissions(
+ new String[] { perm }, PackageManager.MATCH_UNINSTALLED_PACKAGES);
+ for (PackageInfo pi : holding) {
+ if (!Objects.equals("android", pi.packageName)) {
+ failures.add(perm + " held by " + pi.packageName);
+ }
+ }
+ }
+ if (!failures.isEmpty()) {
+ fail("Found permissions granted to packages outside of the core system: "
+ + failures.toString());
+ }
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java b/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
new file mode 100644
index 000000000..8609e3379
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.content.Context.DEVICE_POLICY_SERVICE;
+import static android.content.Context.FINGERPRINT_SERVICE;
+import static android.content.Context.SHORTCUT_SERVICE;
+import static android.content.Context.USB_SERVICE;
+import static android.content.Context.WALLPAPER_SERVICE;
+import static android.content.Context.WIFI_AWARE_SERVICE;
+import static android.content.Context.WIFI_P2P_SERVICE;
+import static android.content.Context.WIFI_SERVICE;
+
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.platform.test.annotations.AppModeInstant;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Some services are not available to instant apps, see {@link Context#getSystemService}.
+ */
+@AppModeInstant
+@RunWith(AndroidJUnit4.class)
+public class ServicesInstantAppsCannotAccessTests {
+ @Test
+ public void cannotGetDevicePolicyManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ DEVICE_POLICY_SERVICE));
+ }
+
+ @Test
+ public void cannotGetFingerprintManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ FINGERPRINT_SERVICE));
+ }
+
+ @Test
+ public void cannotGetShortcutManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ SHORTCUT_SERVICE));
+ }
+
+ @Test
+ public void cannotGetUsbManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ USB_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWallpaperManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WALLPAPER_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiP2pManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_P2P_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiAwareManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_AWARE_SERVICE));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SharedUidPermissionsTest.java b/tests/cts/permission/src/android/permission/cts/SharedUidPermissionsTest.java
new file mode 100644
index 000000000..4966a870b
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SharedUidPermissionsTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static android.Manifest.permission.INTERNET;
+import static android.Manifest.permission.READ_CONTACTS;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.install;
+import static android.permission.cts.PermissionUtils.isPermissionGranted;
+import static android.permission.cts.PermissionUtils.revokePermission;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot read properties of other packages which is needed "
+ + "to grant permissions to them.")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class SharedUidPermissionsTest {
+ /** The package name of all apps used in the test */
+ private static final String PKG_THAT_REQUESTS_PERMISSIONS =
+ "android.permission.cts.appthatrequestpermission";
+ private static final String PKG_THAT_REQUESTS_NO_PERMISSIONS =
+ "android.permission.cts.appthatrequestnopermission";
+
+ private static final String TMP_DIR = "/data/local/tmp/cts-permission/";
+ private static final String APK_THAT_REQUESTS_PERMISSIONS =
+ TMP_DIR + "CtsAppWithSharedUidThatRequestsPermissions.apk";
+ private static final String APK_THAT_REQUESTS_NO_PERMISSIONS =
+ TMP_DIR + "CtsAppWithSharedUidThatRequestsNoPermissions.apk";
+
+ @Before
+ @After
+ public void uninstallTestApps() {
+ uninstallApp(PKG_THAT_REQUESTS_PERMISSIONS);
+ uninstallApp(PKG_THAT_REQUESTS_NO_PERMISSIONS);
+ }
+
+ @Test
+ public void packageGainsRuntimePermissionsWhenJoiningSharedUid() throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS)).isTrue();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isTrue();
+ }
+
+ @Test
+ public void packageGainsNormalPermissionsWhenJoiningSharedUid() throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, INTERNET)).isTrue();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, INTERNET)).isTrue();
+ }
+
+ @Test
+ public void grantingRuntimePermissionAffectsAllPackageInSharedUid() throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS)).isTrue();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isTrue();
+ }
+
+ @Test
+ public void revokingRuntimePermissionAffectsAllPackageInSharedUid() throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+ revokePermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS)).isFalse();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isFalse();
+ }
+
+ @Test
+ public void runtimePermissionsCanBeRevokedOnPackageThatDoesNotDeclarePermission()
+ throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+ revokePermission(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS)).isFalse();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isFalse();
+ }
+
+ @Test
+ @FlakyTest
+ public void runtimePermissionsCanBeGrantedOnPackageThatDoesNotDeclarePermission()
+ throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS)).isTrue();
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isTrue();
+ }
+
+ @Test
+ public void sharedUidLoosesRuntimePermissionWhenLastAppDeclaringItGetsUninstalled()
+ throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ grantPermission(PKG_THAT_REQUESTS_PERMISSIONS, READ_CONTACTS);
+ uninstallApp(PKG_THAT_REQUESTS_PERMISSIONS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, READ_CONTACTS)).isFalse();
+ }
+
+ @Test
+ @FlakyTest
+ public void sharedUidLoosesNormalPermissionWhenLastAppDeclaringItGetsUninstalled()
+ throws Exception {
+ install(APK_THAT_REQUESTS_PERMISSIONS);
+ install(APK_THAT_REQUESTS_NO_PERMISSIONS);
+ uninstallApp(PKG_THAT_REQUESTS_PERMISSIONS);
+
+ assertThat(isPermissionGranted(PKG_THAT_REQUESTS_NO_PERMISSIONS, INTERNET)).isFalse();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ShellCommandPermissionTest.java b/tests/cts/permission/src/android/permission/cts/ShellCommandPermissionTest.java
new file mode 100644
index 000000000..54562d5ee
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ShellCommandPermissionTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.permission.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test shell command capability enforcement
+ */
+@RunWith(AndroidJUnit4.class)
+public class ShellCommandPermissionTest {
+
+ static final int EXPECTED_ERROR_CODE = 255;
+
+ /**
+ * Runs the given command, waits for it to exit, and verifies the return
+ * code indicates failure.
+ */
+ private void executeShellCommandAndWaitForError(String command)
+ throws Exception {
+ try {
+ java.lang.Process proc = Runtime.getRuntime().exec(command);
+ assertThat(proc.waitFor()).isEqualTo(EXPECTED_ERROR_CODE);
+ } catch (InterruptedException e) {
+ fail("Unsuccessful shell command");
+ }
+ }
+
+ @Test
+ public void testTraceIpc() throws Exception {
+ executeShellCommandAndWaitForError(
+ "cmd activity trace-ipc stop --dump-file /data/system/last-fstrim");
+ }
+
+ @Test
+ public void testDumpheap() throws Exception {
+ executeShellCommandAndWaitForError(
+ "cmd activity dumpheap system_server /data/system/last-fstrim");
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/ShellPermissionTest.java b/tests/cts/permission/src/android/permission/cts/ShellPermissionTest.java
new file mode 100644
index 000000000..c4c66564c
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/ShellPermissionTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 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.permission.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Tests that shell has acceptable permissions.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ShellPermissionTest {
+ private static final String LOG_TAG = ShellPermissionTest.class.getSimpleName();
+
+ /** Permissions that shell is NOT permitted to have. */
+ private static final String[] BLACKLISTED_PERMISSIONS = {
+ "android.permission.MANAGE_USERS",
+ "android.permission.NETWORK_STACK",
+ "android.permission.MANAGE_WIFI_COUNTRY_CODE",
+ };
+
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+
+ /**
+ * Verify that the shell uid does not have any of the permissions listed in
+ * {@link #BLACKLISTED_PERMISSIONS}.
+ */
+ @Test
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages. Also the shell "
+ + "is never an instant app, hence this test does not matter for instant apps.")
+ public void testBlacklistedPermissions() throws Exception {
+ final Set<String> blacklist = new HashSet<>(Arrays.asList(BLACKLISTED_PERMISSIONS));
+
+ final PackageManager pm = sContext.getPackageManager();
+ int uid = UserHandle.getUid(UserHandle.myUserId(), UserHandle.getAppId(Process.SHELL_UID));
+ final String[] pkgs = pm.getPackagesForUid(uid);
+ Log.d(LOG_TAG, "SHELL_UID: " + Process.SHELL_UID + " myUserId: "
+ + UserHandle.myUserId() + " uid: " + uid + " pkgs.length: " + pkgs.length);
+ assertNotNull("No SHELL packages were found", pkgs);
+ assertNotEquals("SHELL package list had 0 size", 0, pkgs.length);
+ String pkg = pkgs[0];
+
+ final PackageInfo packageInfo = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
+ assertNotNull("No permissions found for " + pkg, packageInfo.requestedPermissions);
+
+ for (String permission : packageInfo.requestedPermissions) {
+ Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission + " uid: "
+ + uid);
+ assertFalse("SHELL as " + pkg + " contains the illegal permission " + permission,
+ blacklist.contains(permission));
+ }
+ }
+
+ @Test
+ @SystemUserOnly
+ @AppModeFull(reason = "Instant apps cannot read properties of other packages. Also the shell "
+ + "is never an instant app, hence this test does not matter for instant apps.")
+ public void testBlacklistedPermissionsForSystemUser() throws Exception {
+ testBlacklistedPermissions();
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SmsManagerPermissionTest.java b/tests/cts/permission/src/android/permission/cts/SmsManagerPermissionTest.java
new file mode 100644
index 000000000..dd0d9f234
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SmsManagerPermissionTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Test that sending SMS and MMS messages requires permissions.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SmsManagerPermissionTest {
+
+ private static final String SOURCE_ADDRESS = "+15550000000";
+ private static final String DESTINATION_ADDRESS = "+15550000001";
+
+ private boolean mHasTelephony;
+ private SmsManager mSmsManager;
+ private Context mContext;
+ private TelephonyManager mTelephonyManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
+ mHasTelephony = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY);
+ assumeTrue(mHasTelephony); // Don't run these tests if FEATURE_TELEPHONY is not available.
+
+ Log.d("SmsManagerPermissionTest", "mSubId=" + subId);
+
+ mSmsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
+ assertNotNull(mSmsManager);
+ }
+
+ @Test
+ public void testSendTextMessage() {
+ assertFalse("[RERUN] Device does not have SIM card. Use a suitable SIM Card.",
+ isSimCardAbsent());
+
+ assertThrows(SecurityException.class, () -> mSmsManager.sendTextMessage(
+ DESTINATION_ADDRESS, SOURCE_ADDRESS, "Message text", null, null));
+ }
+
+ @Test
+ public void testSendTextMessageWithoutPersisting() {
+ assertFalse("[RERUN] Device does not have SIM card. Use a suitable SIM Card.",
+ isSimCardAbsent());
+
+ assertThrows(SecurityException.class, () -> mSmsManager.sendTextMessageWithoutPersisting(
+ DESTINATION_ADDRESS, SOURCE_ADDRESS, "Message text", null, null));
+ }
+
+ @Test
+ public void testSendMultipartTextMessage() {
+ assertFalse("[RERUN] Device does not have SIM card. Use a suitable SIM Card.",
+ isSimCardAbsent());
+
+ ArrayList<String> messageParts = new ArrayList<>();
+ messageParts.add("Message text");
+ assertThrows(SecurityException.class, () -> mSmsManager.sendMultipartTextMessage(
+ DESTINATION_ADDRESS, SOURCE_ADDRESS, messageParts, null, null));
+ }
+
+ @Test
+ public void testSendDataMessage() {
+ assertFalse("[RERUN] Device does not have SIM card. Use a suitable SIM Card.",
+ isSimCardAbsent());
+
+ assertThrows(SecurityException.class, () -> mSmsManager.sendDataMessage(
+ DESTINATION_ADDRESS, SOURCE_ADDRESS, (short) 1, new byte[]{0, 0, 0}, null, null));
+ }
+
+ @Test
+ public void testSendMultimediaMessage() {
+ assertFalse("[RERUN] Device does not have SIM card. Use a suitable SIM Card.",
+ isSimCardAbsent());
+
+ // Ideally we would provide an Uri to an existing resource, to make sure the
+ // SecurityException is not due to the invalid Uri.
+ Uri uri = Uri.parse("android.resource://android.permission.cts/some-image.png");
+ assertThrows(SecurityException.class,
+ () -> mSmsManager.sendMultimediaMessage(mContext, uri, "", null, null));
+ }
+
+ private boolean isSimCardAbsent() {
+ return ((mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_ABSENT)
+ || (SubscriptionManager.getDefaultSmsSubscriptionId()
+ == SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SplitPermissionTest.java b/tests/cts/permission/src/android/permission/cts/SplitPermissionTest.java
new file mode 100644
index 000000000..a509b3bfe
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SplitPermissionTest.java
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.READ_CALL_LOG;
+import static android.Manifest.permission.READ_CONTACTS;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.permission.cts.PermissionUtils.getAppOp;
+import static android.permission.cts.PermissionUtils.getPermissionFlags;
+import static android.permission.cts.PermissionUtils.getPermissions;
+import static android.permission.cts.PermissionUtils.grantPermission;
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permission.cts.PermissionUtils.revokePermission;
+import static android.permission.cts.PermissionUtils.setPermissionFlags;
+import static android.permission.cts.PermissionUtils.uninstallApp;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.UiAutomation;
+import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
+
+import androidx.annotation.NonNull;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests how split permissions behave.
+ *
+ * <ul>
+ * <li>Default permission grant behavior</li>
+ * <li>Changes to the grant state during upgrade of apps with split permissions</li>
+ * <li>Special behavior of background location</li>
+ * </ul>
+ */
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "Instant apps cannot read state of other packages.")
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class SplitPermissionTest {
+ /** The package name of all apps used in the test */
+ private static final String APP_PKG = "android.permission.cts.appthatrequestpermission";
+
+ private static final String TMP_DIR = "/data/local/tmp/cts-permission/";
+ private static final String APK_CONTACTS_16 =
+ TMP_DIR + "CtsAppThatRequestsContactsPermission16.apk";
+ private static final String APK_CONTACTS_15 =
+ TMP_DIR + "CtsAppThatRequestsContactsPermission15.apk";
+ private static final String APK_CONTACTS_CALLLOG_16 =
+ TMP_DIR + "CtsAppThatRequestsContactsAndCallLogPermission16.apk";
+ private static final String APK_STORAGE_29 =
+ TMP_DIR + "CtsAppThatRequestsStoragePermission29.apk";
+ private static final String APK_STORAGE_28 =
+ TMP_DIR + "CtsAppThatRequestsStoragePermission28.apk";
+ private static final String APK_LOCATION_29 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission29.apk";
+ private static final String APK_LOCATION_28 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission28.apk";
+ private static final String APK_LOCATION_22 =
+ TMP_DIR + "CtsAppThatRequestsLocationPermission22.apk";
+ private static final String APK_LOCATION_BACKGROUND_28 =
+ TMP_DIR + "CtsAppThatRequestsLocationAndBackgroundPermission28.apk";
+ private static final String APK_LOCATION_BACKGROUND_29 =
+ TMP_DIR + "CtsAppThatRequestsLocationAndBackgroundPermission29.apk";
+ private static final String APK_SHARED_UID_LOCATION_29 =
+ TMP_DIR + "CtsAppWithSharedUidThatRequestsLocationPermission29.apk";
+ private static final String APK_SHARED_UID_LOCATION_28 =
+ TMP_DIR + "CtsAppWithSharedUidThatRequestsLocationPermission28.apk";
+
+ private static final UiAutomation sUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ /**
+ * Assert that {@link #APP_PKG} requests a certain permission.
+ *
+ * @param permName The permission that needs to be requested
+ */
+ private void assertRequestsPermission(@NonNull String permName) throws Exception {
+ assertThat(getPermissions(APP_PKG)).contains(permName);
+ }
+
+ /**
+ * Assert that {@link #APP_PKG} <u>does not</u> request a certain permission.
+ *
+ * @param permName The permission that needs to be not requested
+ */
+ private void assertNotRequestsPermission(@NonNull String permName) throws Exception {
+ assertThat(getPermissions(APP_PKG)).doesNotContain(permName);
+ }
+
+ /**
+ * Assert that a permission is granted to {@link #APP_PKG}.
+ *
+ * @param permName The permission that needs to be granted
+ */
+ private void assertPermissionGranted(@NonNull String permName) throws Exception {
+ eventually(() -> assertWithMessage(permName + " is granted").that(
+ isGranted(APP_PKG, permName)).isTrue());
+ }
+
+ /**
+ * Assert that a permission is <u>not </u> granted to {@link #APP_PKG}.
+ *
+ * @param permName The permission that should not be granted
+ */
+ private void assertPermissionRevoked(@NonNull String permName) throws Exception {
+ assertWithMessage(permName + " is granted").that(isGranted(APP_PKG, permName)).isFalse();
+ }
+
+ /**
+ * Install an APK.
+ *
+ * @param apkFile The apk to install
+ */
+ public void install(@NonNull String apkFile) {
+ PermissionUtils.install(apkFile);
+ }
+
+ @After
+ public void uninstallTestApp() {
+ uninstallApp(APP_PKG);
+ }
+
+ /**
+ * Apps with a targetSDK after the split should <u>not</u> have been added implicitly the new
+ * permission.
+ */
+ @Test
+ public void permissionsDoNotSplitWithHighTargetSDK() throws Exception {
+ install(APK_LOCATION_29);
+
+ assertRequestsPermission(ACCESS_COARSE_LOCATION);
+ assertNotRequestsPermission(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * Apps with a targetSDK after the split should <u>not</u> have been added implicitly the new
+ * permission.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void permissionsDoNotSplitWithHighTargetSDKPreM() throws Exception {
+ install(APK_CONTACTS_16);
+
+ assertRequestsPermission(READ_CONTACTS);
+ assertNotRequestsPermission(READ_CALL_LOG);
+ }
+
+ /**
+ * Apps with a targetSDK before the split should have been added implicitly the new permission.
+ */
+ @Test
+ public void permissionsSplitWithLowTargetSDK() throws Exception {
+ install(APK_LOCATION_28);
+
+ assertRequestsPermission(ACCESS_COARSE_LOCATION);
+ assertRequestsPermission(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * Apps with a targetSDK before the split should have been added implicitly the new permission.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void permissionsSplitWithLowTargetSDKPreM() throws Exception {
+ install(APK_CONTACTS_15);
+
+ assertRequestsPermission(READ_CONTACTS);
+ assertRequestsPermission(READ_CALL_LOG);
+ }
+
+ /**
+ * Permissions are revoked by default for post-M apps
+ */
+ @Test
+ public void nonInheritedStateHighTargetSDK() throws Exception {
+ install(APK_LOCATION_29);
+
+ assertPermissionRevoked(ACCESS_COARSE_LOCATION);
+ }
+
+ /**
+ * Permissions are granted by default for pre-M apps
+ */
+ @Test
+ public void nonInheritedStateHighLowTargetSDKPreM() throws Exception {
+ install(APK_CONTACTS_15);
+
+ assertPermissionGranted(READ_CONTACTS);
+ }
+
+ /**
+ * Permissions are revoked by default for post-M apps. This also applies to permissions added
+ * implicitly due to splits.
+ */
+ @Test
+ public void nonInheritedStateLowTargetSDK() throws Exception {
+ install(APK_LOCATION_28);
+
+ assertPermissionRevoked(ACCESS_COARSE_LOCATION);
+ assertPermissionRevoked(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * Permissions are granted by default for pre-M apps. This also applies to permissions added
+ * implicitly due to splits.
+ */
+ @Test
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void nonInheritedStateLowTargetSDKPreM() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ install(APK_CONTACTS_15);
+
+ assertPermissionGranted(READ_CONTACTS);
+ assertPermissionGranted(READ_CALL_LOG);
+ }
+
+ /**
+ * The background location permission granted by default for pre-M apps.
+ */
+ @Test
+ public void backgroundLocationPermissionDefaultGrantPreM() throws Exception {
+ install(APK_LOCATION_22);
+
+ assertPermissionGranted(ACCESS_COARSE_LOCATION);
+ assertPermissionGranted(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * If a permission was granted before the split happens, the new permission should inherit the
+ * granted state.
+ */
+ @FlakyTest(bugId = 152580253)
+ @MtsIgnore(bugId = 152580253)
+ @Test
+ public void inheritGrantedPermissionState() throws Exception {
+ install(APK_LOCATION_29);
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ install(APK_LOCATION_28);
+
+ assertPermissionGranted(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * If a permission was granted before the split happens, the new permission should inherit the
+ * granted state.
+ *
+ * <p>App using a shared uid
+ */
+ @Test
+ public void inheritGrantedPermissionStateSharedUidApp() throws Exception {
+ install(APK_SHARED_UID_LOCATION_29);
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ install(APK_SHARED_UID_LOCATION_28);
+
+ assertPermissionGranted(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * If a permission has flags before the split happens, the new permission should inherit the
+ * flags.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @FlakyTest(bugId = 152580253)
+ @MtsIgnore(bugId = 152580253)
+ @Test
+ public void inheritFlagsPreM() {
+ install(APK_CONTACTS_16);
+ setPermissionFlags(APP_PKG, READ_CONTACTS, FLAG_PERMISSION_USER_SET,
+ FLAG_PERMISSION_USER_SET);
+
+ install(APK_CONTACTS_15);
+
+ assertEquals(FLAG_PERMISSION_USER_SET,
+ getPermissionFlags(APP_PKG, READ_CALL_LOG) & FLAG_PERMISSION_USER_SET);
+ }
+
+ /**
+ * If a permission has flags before the split happens, the new permission should inherit the
+ * flags.
+ */
+ @FlakyTest(bugId = 152580253)
+ @MtsIgnore(bugId = 152580253)
+ @Test
+ public void inheritFlags() {
+ install(APK_LOCATION_29);
+ setPermissionFlags(APP_PKG, ACCESS_COARSE_LOCATION, FLAG_PERMISSION_USER_SET,
+ FLAG_PERMISSION_USER_SET);
+
+ install(APK_LOCATION_28);
+
+ assertEquals(FLAG_PERMISSION_USER_SET,
+ getPermissionFlags(APP_PKG, ACCESS_BACKGROUND_LOCATION) & FLAG_PERMISSION_USER_SET);
+ }
+
+ /**
+ * If a permission was granted before the split happens, the new permission should inherit the
+ * granted state.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void inheritGrantedPermissionStatePreM() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ install(APK_CONTACTS_16);
+
+ install(APK_CONTACTS_15);
+
+ assertPermissionGranted(READ_CALL_LOG);
+ }
+
+ /**
+ * If a permission was revoked before the split happens, the new permission should inherit the
+ * revoked state.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void inheritRevokedPermissionState() throws Exception {
+ install(APK_LOCATION_29);
+
+ install(APK_LOCATION_28);
+
+ assertPermissionRevoked(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * If a permission was revoked before the split happens, the new permission should inherit the
+ * revoked state.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void inheritRevokedPermissionStatePreM() throws Exception {
+ install(APK_CONTACTS_16);
+ revokePermission(APP_PKG, READ_CONTACTS);
+
+ install(APK_CONTACTS_15);
+
+ /*
+ * Ideally the new permission should inherit from it's base permission, but this is tricky
+ * to implement.
+ * The new permissions need to be reviewed, hence the pre-review state really does not
+ * matter anyway.
+ */
+ // assertPermissionRevoked(READ_CALL_LOG);
+ assertThat(getPermissionFlags(APP_PKG, READ_CALL_LOG)
+ & FLAG_PERMISSION_REVIEW_REQUIRED).isEqualTo(FLAG_PERMISSION_REVIEW_REQUIRED);
+ }
+
+ /**
+ * It should be possible to grant a permission implicitly added due to a split.
+ */
+ @Test
+ public void grantNewSplitPermissionState() throws Exception {
+ install(APK_LOCATION_28);
+
+ // Background permission can only be granted together with foreground permission
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ assertPermissionGranted(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * It should be possible to grant a permission implicitly added due to a split.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void grantNewSplitPermissionStatePreM() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ install(APK_CONTACTS_15);
+ revokePermission(APP_PKG, READ_CONTACTS);
+
+ grantPermission(APP_PKG, READ_CALL_LOG);
+
+ assertPermissionGranted(READ_CALL_LOG);
+ }
+
+ /**
+ * It should be possible to revoke a permission implicitly added due to a split.
+ */
+ @Test
+ public void revokeNewSplitPermissionState() throws Exception {
+ install(APK_LOCATION_28);
+
+ // Background permission can only be granted together with foreground permission
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ revokePermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ assertPermissionRevoked(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * It should be possible to revoke a permission implicitly added due to a split.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void revokeNewSplitPermissionStatePreM() throws Exception {
+ install(APK_CONTACTS_15);
+
+ revokePermission(APP_PKG, READ_CALL_LOG);
+
+ assertPermissionRevoked(READ_CALL_LOG);
+ }
+
+ /**
+ * An implicit permission should get revoked when the app gets updated and now requests the
+ * permission.
+ */
+ @Test
+ public void newPermissionGetRevokedOnUpgrade() throws Exception {
+ install(APK_LOCATION_28);
+
+ // Background permission can only be granted together with foreground permission
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ install(APK_LOCATION_BACKGROUND_29);
+
+ assertPermissionRevoked(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * An implicit background permission should get revoked when the app gets updated and now
+ * requests the permission. Revoking a background permission should have changed the app-op of
+ * the foreground permission.
+ */
+ @Test
+ public void newBackgroundPermissionGetRevokedOnUpgrade() throws Exception {
+ install(APK_LOCATION_28);
+
+ // Background permission can only be granted together with foreground permission
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ install(APK_LOCATION_BACKGROUND_29);
+
+ eventually(() -> assertWithMessage("foreground app-op").that(
+ getAppOp(APP_PKG, ACCESS_COARSE_LOCATION)).isEqualTo(MODE_FOREGROUND));
+ }
+
+ /**
+ * An implicit permission should get revoked when the app gets updated and now requests the
+ * permission. This even happens if the app is not targeting the SDK the permission was split
+ * in.
+ */
+ @Test
+ public void newPermissionGetRevokedOnUpgradeBeforeSplitSDK() throws Exception {
+ install(APK_LOCATION_28);
+
+ // Background permission can only be granted together with foreground permission
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+ grantPermission(APP_PKG, ACCESS_BACKGROUND_LOCATION);
+
+ // Background location was introduced in SDK 29. Hence an app targeting 28 is usually
+ // unaware of this permission. If the app declares that it is aware by adding the permission
+ // in the manifest the permission will get revoked. This allows the app to request the
+ // permission from the user.
+ install(APK_LOCATION_BACKGROUND_28);
+
+ assertPermissionRevoked(ACCESS_BACKGROUND_LOCATION);
+ }
+
+ /**
+ * An implicit permission should <u>not</u> get revoked when the app gets updated as pre-M apps
+ * cannot deal with revoked permissions. Hence only the user should ever explicitly do that.
+ */
+ @Test
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void newPermissionGetRevokedOnUpgradePreM() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ install(APK_CONTACTS_15);
+
+ install(APK_CONTACTS_CALLLOG_16);
+
+ assertPermissionGranted(READ_CALL_LOG);
+ }
+
+ /**
+ * When a requested permission was granted before upgrade it should still be granted.
+ */
+ @Test
+ public void oldPermissionStaysGrantedOnUpgrade() throws Exception {
+ install(APK_LOCATION_28);
+ grantPermission(APP_PKG, ACCESS_COARSE_LOCATION);
+
+ install(APK_LOCATION_BACKGROUND_29);
+
+ assertPermissionGranted(ACCESS_COARSE_LOCATION);
+ }
+
+ /**
+ * When a requested permission was granted before upgrade it should still be granted.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void oldPermissionStaysGrantedOnUpgradePreM() throws Exception {
+ install(APK_CONTACTS_15);
+
+ install(APK_CONTACTS_CALLLOG_16);
+
+ assertPermissionGranted(READ_CONTACTS);
+ }
+
+ /**
+ * When a requested permission was revoked before upgrade it should still be revoked.
+ */
+ @Test
+ public void oldPermissionStaysRevokedOnUpgrade() throws Exception {
+ install(APK_LOCATION_28);
+
+ install(APK_LOCATION_BACKGROUND_29);
+
+ assertPermissionRevoked(ACCESS_COARSE_LOCATION);
+ }
+
+ /**
+ * When a requested permission was revoked before upgrade it should still be revoked.
+ *
+ * <p>(Pre-M version of test)
+ */
+ @Test
+ public void oldPermissionStaysRevokedOnUpgradePreM() throws Exception {
+ install(APK_CONTACTS_15);
+ revokePermission(APP_PKG, READ_CONTACTS);
+
+ install(APK_CONTACTS_CALLLOG_16);
+
+ assertPermissionRevoked(READ_CONTACTS);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/SplitPermissionsSystemTest.java b/tests/cts/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
new file mode 100755
index 000000000..776a1065e
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/SplitPermissionsSystemTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2018 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.permission.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.ACCESS_MEDIA_LOCATION;
+import static android.Manifest.permission.BLUETOOTH;
+import static android.Manifest.permission.BLUETOOTH_ADMIN;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.Manifest.permission.BLUETOOTH_SCAN;
+import static android.Manifest.permission.BODY_SENSORS;
+import static android.Manifest.permission.BODY_SENSORS_BACKGROUND;
+import static android.Manifest.permission.READ_CALL_LOG;
+import static android.Manifest.permission.READ_CONTACTS;
+import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.Manifest.permission.READ_MEDIA_AUDIO;
+import static android.Manifest.permission.READ_MEDIA_IMAGES;
+import static android.Manifest.permission.READ_MEDIA_VIDEO;
+import static android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED;
+import static android.Manifest.permission.READ_PHONE_STATE;
+import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
+import static android.Manifest.permission.WRITE_CALL_LOG;
+import static android.Manifest.permission.WRITE_CONTACTS;
+import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.os.Build;
+import android.permission.PermissionManager;
+import android.permission.PermissionManager.SplitPermissionInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+public class SplitPermissionsSystemTest {
+
+ private static final int NO_TARGET = Build.VERSION_CODES.CUR_DEVELOPMENT + 1;
+
+ private List<SplitPermissionInfo> mSplitPermissions;
+
+ @Before
+ public void before() {
+ Context context = InstrumentationRegistry.getContext();
+ PermissionManager permissionManager = (PermissionManager) context.getSystemService(
+ Context.PERMISSION_SERVICE);
+ mSplitPermissions = permissionManager.getSplitPermissions();
+ }
+
+ @Test
+ public void validateAndroidSystem() {
+ assumeTrue(ApiLevelUtil.isAtLeast(Build.VERSION_CODES.Q));
+
+ Set<SplitPermissionInfo> seenSplits = new HashSet<>(6);
+
+ for (SplitPermissionInfo split : mSplitPermissions) {
+ String splitPermission = split.getSplitPermission();
+ boolean isAndroid = splitPermission.startsWith("android");
+
+ if (!isAndroid) {
+ continue;
+ }
+
+ assertThat(seenSplits).doesNotContain(split);
+ seenSplits.add(split);
+
+ List<String> newPermissions = split.getNewPermissions();
+
+ switch (splitPermission) {
+ case ACCESS_FINE_LOCATION:
+ // Q declares multiple for ACCESS_FINE_LOCATION, so assert both exist
+ if (newPermissions.contains(ACCESS_COARSE_LOCATION)) {
+ assertSplit(split, NO_TARGET, ACCESS_COARSE_LOCATION);
+ } else {
+ assertSplit(split, Build.VERSION_CODES.Q, ACCESS_BACKGROUND_LOCATION);
+ }
+ break;
+ case WRITE_EXTERNAL_STORAGE:
+ if (newPermissions.contains(READ_EXTERNAL_STORAGE)) {
+ assertSplit(split, NO_TARGET, READ_EXTERNAL_STORAGE);
+ } else if (newPermissions.contains(ACCESS_MEDIA_LOCATION)) {
+ assertSplit(split, Build.VERSION_CODES.Q, ACCESS_MEDIA_LOCATION);
+ } else if (newPermissions.contains(READ_MEDIA_AUDIO)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_AUDIO);
+ } else if (newPermissions.contains(READ_MEDIA_VIDEO)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_VIDEO);
+ } else if (newPermissions.contains(READ_MEDIA_IMAGES)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_IMAGES);
+ }
+ break;
+ case READ_CONTACTS:
+ assertSplit(split, Build.VERSION_CODES.JELLY_BEAN, READ_CALL_LOG);
+ break;
+ case WRITE_CONTACTS:
+ assertSplit(split, Build.VERSION_CODES.JELLY_BEAN, WRITE_CALL_LOG);
+ break;
+ case ACCESS_COARSE_LOCATION:
+ assertSplit(split, Build.VERSION_CODES.Q, ACCESS_BACKGROUND_LOCATION);
+ break;
+ case READ_EXTERNAL_STORAGE:
+ if (newPermissions.contains(ACCESS_MEDIA_LOCATION)) {
+ assertSplit(split, Build.VERSION_CODES.Q, ACCESS_MEDIA_LOCATION);
+ } else if (newPermissions.contains(READ_MEDIA_AUDIO)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_AUDIO);
+ } else if (newPermissions.contains(READ_MEDIA_VIDEO)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_VIDEO);
+ } else if (newPermissions.contains(READ_MEDIA_IMAGES)) {
+ assertSplit(split, Build.VERSION_CODES.S_V2 + 1, READ_MEDIA_IMAGES);
+ }
+ break;
+ case READ_PRIVILEGED_PHONE_STATE:
+ assertSplit(split, NO_TARGET, READ_PHONE_STATE);
+ break;
+ case BLUETOOTH_CONNECT:
+ assertSplit(split, Build.VERSION_CODES.S, BLUETOOTH, BLUETOOTH_ADMIN);
+ break;
+ case BLUETOOTH_SCAN:
+ assertSplit(split, Build.VERSION_CODES.S, BLUETOOTH, BLUETOOTH_ADMIN);
+ break;
+ case BODY_SENSORS:
+ assertSplit(split, Build.VERSION_CODES.TIRAMISU, BODY_SENSORS_BACKGROUND);
+ break;
+ case ACCESS_MEDIA_LOCATION:
+ case READ_MEDIA_IMAGES:
+ case READ_MEDIA_VIDEO:
+ assertSplit(split, READ_MEDIA_VISUAL_USER_SELECTED);
+ break;
+ }
+ }
+
+ assertEquals(24, seenSplits.size());
+ }
+
+ private void assertSplit(SplitPermissionInfo split, int targetSdk, String... permission) {
+ assertThat(split.getNewPermissions()).containsExactlyElementsIn(permission);
+ assertThat(split.getTargetSdk()).isEqualTo(targetSdk);
+ }
+
+ private void assertSplit(SplitPermissionInfo split, String... permission) {
+ assertThat(split.getNewPermissions()).containsExactlyElementsIn(permission);
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/StorageEscalationTest.kt b/tests/cts/permission/src/android/permission/cts/StorageEscalationTest.kt
new file mode 100644
index 000000000..2060a1dc1
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/StorageEscalationTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 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.permission.cts
+
+import android.Manifest.permission.ACCESS_MEDIA_LOCATION
+import android.Manifest.permission.READ_EXTERNAL_STORAGE
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.content.Context
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Process
+import android.os.UserHandle
+import android.platform.test.annotations.AppModeFull
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeNoException
+import org.junit.Before
+import org.junit.Test
+
+@AppModeFull
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+class StorageEscalationTest {
+ companion object {
+ private const val APK_DIRECTORY = "/data/local/tmp/cts-permission"
+ const val APP_APK_PATH_28 = "$APK_DIRECTORY/CtsStorageEscalationApp28.apk"
+ const val APP_APK_PATH_29_SCOPED = "$APK_DIRECTORY/CtsStorageEscalationApp29Scoped.apk"
+ const val APP_APK_PATH_29_FULL = "$APK_DIRECTORY/CtsStorageEscalationApp29Full.apk"
+ const val APP_PACKAGE_NAME = "android.permission.cts.storageescalation"
+ const val DELAY_TIME_MS: Long = 200
+ val permissions = listOf<String>(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE,
+ ACCESS_MEDIA_LOCATION)
+ }
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = instrumentation.context
+ private val uiAutomation: UiAutomation = instrumentation.uiAutomation
+ private var secondaryUserId: Int? = null
+
+ @Before
+ @After
+ fun uninstallApp() {
+ SystemUtil.runShellCommand("pm uninstall $APP_PACKAGE_NAME --user ALL")
+ }
+
+ private fun installPackage(apk: String) {
+ var userString = ""
+ secondaryUserId?.let { userId ->
+ userString = " --user $userId"
+ }
+ val result = SystemUtil.runShellCommandOrThrow("pm install -r$userString $apk")
+ assertTrue("Expected output to contain \"Success\", but was \"$result\"",
+ result.contains("Success"))
+ }
+
+ private fun createSecondaryUser() {
+ val createUserOutput: String = SystemUtil.runShellCommand("pm create-user secondary")
+ var formatException: Exception? = null
+ val userId = try {
+ createUserOutput.split(" id ".toRegex())[1].trim { it <= ' ' }.toInt()
+ } catch (e: Exception) {
+ formatException = e
+ -1
+ }
+ assumeNoException("Failed to parse userId from $createUserOutput", formatException)
+ SystemUtil.runShellCommand("am start-user -w $userId")
+ secondaryUserId = userId
+ }
+
+ @After
+ fun removeSecondaryUser() {
+ secondaryUserId?.let { userId ->
+ SystemUtil.runShellCommand("pm remove-user $userId")
+ secondaryUserId = null
+ }
+ }
+
+ private fun grantStoragePermissions() {
+ for (permName in permissions) {
+ var user = Process.myUserHandle()
+ secondaryUserId?.let {
+ user = UserHandle.of(it)
+ }
+ uiAutomation.grantRuntimePermissionAsUser(APP_PACKAGE_NAME, permName, user)
+ }
+ }
+
+ private fun assertStoragePermissionState(granted: Boolean) {
+ for (permName in permissions) {
+ var userContext = context
+ secondaryUserId?.let { userId ->
+ SystemUtil.runWithShellPermissionIdentity {
+ userContext = context.createPackageContextAsUser(
+ APP_PACKAGE_NAME, 0, UserHandle.of(userId))
+ }
+ }
+ Assert.assertEquals(granted, userContext.packageManager.checkPermission(permName,
+ APP_PACKAGE_NAME) == PackageManager.PERMISSION_GRANTED)
+ }
+ }
+
+ @Test
+ fun testCannotEscalateWithSdkDowngrade() {
+ runStorageEscalationTest(APP_APK_PATH_29_SCOPED, APP_APK_PATH_28)
+ }
+
+ @Test
+ fun testCannotEscalateWithNewManifestLegacyRequest() {
+ runStorageEscalationTest(APP_APK_PATH_29_SCOPED, APP_APK_PATH_29_FULL)
+ }
+
+ @Test
+ fun testCannotEscalateWithSdkDowngradeSecondary() {
+ createSecondaryUser()
+ runStorageEscalationTest(APP_APK_PATH_29_SCOPED, APP_APK_PATH_28)
+ }
+
+ @Test
+ fun testCannotEscalateWithNewManifestLegacyRequestSecondary() {
+ createSecondaryUser()
+ runStorageEscalationTest(APP_APK_PATH_29_SCOPED, APP_APK_PATH_29_FULL)
+ }
+
+ private fun runStorageEscalationTest(startPackageApk: String, finishPackageApk: String) {
+ installPackage(startPackageApk)
+ grantStoragePermissions()
+ assertStoragePermissionState(granted = true)
+ installPackage(finishPackageApk)
+ // permission revoke is async, so wait a short period
+ Thread.sleep(DELAY_TIME_MS)
+ assertStoragePermissionState(granted = false)
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/TvPermissionTest.java b/tests/cts/permission/src/android/permission/cts/TvPermissionTest.java
new file mode 100644
index 000000000..e61b2667d
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/TvPermissionTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 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.permission.cts;
+
+import android.content.ContentValues;
+import android.content.pm.PackageManager;
+import android.media.tv.TvContract;
+import android.net.Uri;
+import android.platform.test.annotations.AppModeFull;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests for TV API related permissions.
+ */
+public class TvPermissionTest extends AndroidTestCase {
+ private static final String DUMMY_INPUT_ID = "dummy";
+
+ private boolean mHasTvInputFramework;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mHasTvInputFramework = getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_LIVE_TV);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void verifyInsert(Uri uri, String tableName) throws Exception {
+ try {
+ ContentValues values = new ContentValues();
+ getContext().getContentResolver().insert(uri, values);
+ fail("Accessing " + tableName + " table should require WRITE_EPG_DATA permission.");
+ } catch (SecurityException e) {
+ // Expected exception
+ } catch (IllegalArgumentException e) {
+ // TvProvider is not visable for instant app
+ }
+ }
+
+ public void verifyUpdate(Uri uri, String tableName) throws Exception {
+ try {
+ ContentValues values = new ContentValues();
+ getContext().getContentResolver().update(uri, values, null, null);
+ fail("Accessing " + tableName + " table should require WRITE_EPG_DATA permission.");
+ } catch (SecurityException e) {
+ // Expected exception
+ } catch (IllegalArgumentException e) {
+ // TvProvider is not visable for instant app
+ }
+ }
+
+ public void verifyDelete(Uri uri, String tableName) throws Exception {
+ try {
+ getContext().getContentResolver().delete(uri, null, null);
+ fail("Accessing " + tableName + " table should require WRITE_EPG_DATA permission.");
+ } catch (SecurityException e) {
+ // Expected exception
+ } catch (IllegalArgumentException e) {
+ // TvProvider is not visable for instant app
+ }
+ }
+
+ @AppModeFull
+ public void testInsertChannels() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyInsert(TvContract.Channels.CONTENT_URI, "channels");
+ }
+
+ @AppModeFull
+ public void testUpdateChannels() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyUpdate(TvContract.Channels.CONTENT_URI, "channels");
+ }
+
+ @AppModeFull
+ public void testDeleteChannels() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyDelete(TvContract.Channels.CONTENT_URI, "channels");
+ }
+
+ @AppModeFull
+ public void testInsertPrograms() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyInsert(TvContract.Programs.CONTENT_URI, "programs");
+ }
+
+ @AppModeFull
+ public void testUpdatePrograms() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyUpdate(TvContract.Programs.CONTENT_URI, "programs");
+ }
+
+ @AppModeFull
+ public void testDeletePrograms() throws Exception {
+ if (!mHasTvInputFramework) return;
+ verifyDelete(TvContract.Programs.CONTENT_URI, "programs");
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/UndefinedGroupPermissionTest.kt b/tests/cts/permission/src/android/permission/cts/UndefinedGroupPermissionTest.kt
new file mode 100644
index 000000000..a49b7a9da
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/UndefinedGroupPermissionTest.kt
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2020 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.permission.cts
+
+import android.Manifest.permission.CAMERA
+import android.Manifest.permission.RECORD_AUDIO
+import android.app.Instrumentation
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Process
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.UiObjectNotFoundException
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
+import java.util.regex.Pattern
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests that the permissioncontroller behaves normally when an app defines a permission in the
+ * android.permission-group.UNDEFINED group
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+class UndefinedGroupPermissionTest {
+ private var mInstrumentation: Instrumentation? = null
+ private var mUiDevice: UiDevice? = null
+ private var mContext: Context? = null
+ private var mPm: PackageManager? = null
+ private var mAllowButtonText: Pattern? = null
+ private var mDenyButtonText: Pattern? = null
+
+ @Before
+ fun install() {
+ SystemUtil.runShellCommand("pm uninstall $APP_PKG_NAME")
+ SystemUtil.runShellCommandOrThrow("pm install -r " +
+ TEST_APP_DEFINES_UNDEFINED_PERMISSION_GROUP_ELEMENT_APK)
+ }
+
+ @Before
+ fun setup() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation()
+ mUiDevice = UiDevice.getInstance(mInstrumentation!!)
+ mContext = mInstrumentation?.targetContext
+ mPm = mContext?.packageManager
+ val permissionControllerResources = mContext?.createPackageContext(
+ mContext?.packageManager?.permissionControllerPackageName, 0)?.resources
+ mAllowButtonText = Pattern.compile(
+ Pattern.quote(requireNotNull(permissionControllerResources?.getString(
+ permissionControllerResources.getIdentifier(
+ "grant_dialog_button_allow", "string",
+ "com.android.permissioncontroller")))),
+ Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE)
+ mDenyButtonText = Pattern.compile(
+ Pattern.quote(requireNotNull(permissionControllerResources?.getString(
+ permissionControllerResources.getIdentifier(
+ "grant_dialog_button_deny", "string",
+ "com.android.permissioncontroller")))),
+ Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE)
+ }
+
+ @Before
+ fun wakeUpScreenAndUnlock() {
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP")
+ SystemUtil.runShellCommand("input keyevent KEYCODE_MENU")
+ }
+
+ @Test
+ fun testOtherGroupPermissionsNotGranted_1() {
+ testOtherGroupPermissionsNotGranted(CAMERA, RECORD_AUDIO)
+ }
+
+ @Test
+ fun testOtherGroupPermissionsNotGranted_2() {
+ testOtherGroupPermissionsNotGranted(TEST, RECORD_AUDIO)
+ }
+
+ @Test
+ fun testOtherGroupPermissionsNotGranted_3() {
+ testOtherGroupPermissionsNotGranted(CAMERA, TEST)
+ }
+
+ /**
+ * When the custom permission is granted nothing else gets granted as a byproduct.
+ */
+ @Test
+ fun testCustomPermissionGrantedAlone() {
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(CAMERA, APP_PKG_NAME))
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(RECORD_AUDIO, APP_PKG_NAME))
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(TEST, APP_PKG_NAME))
+ eventually {
+ startRequestActivity(arrayOf(TEST))
+ mUiDevice!!.waitForIdle()
+ Thread.sleep(2000)
+ findAllowButton().click()
+ }
+ eventually {
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(CAMERA, APP_PKG_NAME))
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(RECORD_AUDIO, APP_PKG_NAME))
+ Assert.assertEquals(PackageManager.PERMISSION_GRANTED,
+ mPm!!.checkPermission(TEST, APP_PKG_NAME))
+ }
+ }
+
+ @After
+ fun uninstall() {
+ SystemUtil.runShellCommand("pm uninstall $APP_PKG_NAME")
+ }
+
+ fun findAllowButton(): UiObject2 {
+ return if (mContext?.packageManager
+ ?.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) == true) {
+ waitFindObject(By.text(mAllowButtonText!!), 2000)
+ } else {
+ waitFindObject(By.res(
+ "com.android.permissioncontroller:id/permission_allow_button"),
+ 2000)
+ }
+ }
+
+ /**
+ * If app has one permission granted, then it can't grant itself another permission for free.
+ */
+ fun testOtherGroupPermissionsNotGranted(grantedPerm: String, targetPermission: String) {
+ // Grant the permission in the background
+ SystemUtil.runWithShellPermissionIdentity {
+ mPm!!.grantRuntimePermission(
+ APP_PKG_NAME, grantedPerm, Process.myUserHandle())
+ }
+ Assert.assertEquals("$grantedPerm not granted.", PackageManager.PERMISSION_GRANTED,
+ mPm!!.checkPermission(grantedPerm, APP_PKG_NAME))
+
+ // If the dialog shows, success. If not then either the UI is broken or the permission was
+ // granted in the background.
+ eventually {
+ startRequestActivity(arrayOf(targetPermission))
+ mUiDevice!!.waitForIdle()
+ try {
+ if (mContext?.packageManager
+ ?.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) == true) {
+ waitFindObject(By.text(mDenyButtonText!!), 2000)
+ } else if (mContext?.packageManager
+ ?.hasSystemFeature(PackageManager.FEATURE_WATCH) == true) {
+ waitFindObject(By.res(ALLOW_BUTTON), 2000)
+ } else {
+ waitFindObject(By.res(GRANT_DIALOG), 2000)
+ }
+ } catch (e: UiObjectNotFoundException) {
+ Assert.assertEquals("grant dialog never showed.",
+ PackageManager.PERMISSION_GRANTED,
+ mPm!!.checkPermission(targetPermission, APP_PKG_NAME))
+ }
+ }
+ Assert.assertEquals(PackageManager.PERMISSION_DENIED,
+ mPm!!.checkPermission(targetPermission, APP_PKG_NAME))
+ }
+
+ private fun startRequestActivity(permissions: Array<String>) {
+ mContext!!.startActivity(Intent()
+ .setComponent(
+ ComponentName(APP_PKG_NAME, "$APP_PKG_NAME.RequestPermissions"))
+ .putExtra(EXTRA_PERMISSIONS, permissions)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+ }
+
+ companion object {
+ private const val TEST_APP_DEFINES_UNDEFINED_PERMISSION_GROUP_ELEMENT_APK =
+ "/data/local/tmp/cts-permission/AppThatDefinesUndefinedPermissionGroupElement.apk"
+ private const val APP_PKG_NAME = "android.permission.cts.appthatrequestpermission"
+ private const val EXTRA_PERMISSIONS =
+ "android.permission.cts.appthatrequestpermission.extra.PERMISSIONS"
+ private const val GRANT_DIALOG = "com.android.permissioncontroller:id/grant_dialog"
+ private const val ALLOW_BUTTON =
+ "com.android.permissioncontroller:id/permission_allow_button"
+ const val TEST = "android.permission.cts.appthatrequestpermission.TEST"
+ }
+}
diff --git a/tests/cts/permission/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl b/tests/cts/permission/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl
new file mode 100644
index 000000000..be92ed160
--- /dev/null
+++ b/tests/cts/permission/src/android/permission/cts/appthataccesseslocation/IAccessLocationOnCommand.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 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.permission.cts.appthataccesseslocation;
+
+interface IAccessLocationOnCommand {
+ /** Access location on command */
+ void accessLocation();
+} \ No newline at end of file
diff --git a/tests/cts/permission/telephony/Android.bp b/tests/cts/permission/telephony/Android.bp
new file mode 100644
index 000000000..bbfe06c55
--- /dev/null
+++ b/tests/cts/permission/telephony/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionTestCasesTelephony",
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+ static_libs: [
+ "ctstestrunner-axt",
+ "compatibility-device-util-axt",
+ ],
+ srcs: ["src/**/*.java"],
+ sdk_version: "test_current",
+}
diff --git a/tests/cts/permission/telephony/AndroidManifest.xml b/tests/cts/permission/telephony/AndroidManifest.xml
new file mode 100644
index 000000000..0349880e2
--- /dev/null
+++ b/tests/cts/permission/telephony/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.telephony" android:targetSandboxVersion="2">
+
+ <!--
+ The CTS stubs package cannot be used as the target application here,
+ since that requires many permissions to be set. Instead, specify this
+ package itself as the target and include any stub activities needed.
+
+ This test package uses the default InstrumentationTestRunner, because
+ the InstrumentationCtsTestRunner is only available in the stubs
+ package. That runner cannot be added to this package either, since it
+ relies on hidden APIs.
+ -->
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permission.cts.telephony"
+ android:label="CTS tests of android.permission">
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/cts/permission/telephony/AndroidTest.xml b/tests/cts/permission/telephony/AndroidTest.xml
new file mode 100644
index 000000000..13ee78bcc
--- /dev/null
+++ b/tests/cts/permission/telephony/AndroidTest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Config for CTS Telephony Permission test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+
+ <!-- Telephony permission tests do not use any permission not available to instant apps. -->
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+
+ <!-- Disable package verifier before installing APKs -->
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ <option name="force-skip-system-props" value="true" />
+ </target_preparer>
+
+ <!-- Install main test suite apk -->
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionTestCasesTelephony.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permission.cts.telephony" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/tests/cts/permission/telephony/OWNERS b/tests/cts/permission/telephony/OWNERS
new file mode 100644
index 000000000..446cf1a00
--- /dev/null
+++ b/tests/cts/permission/telephony/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+# Bug component: 20868
+include platform/cts:/tests/tests/telephony/OWNERS \ No newline at end of file
diff --git a/tests/cts/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java b/tests/cts/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java
new file mode 100644
index 000000000..3605be21a
--- /dev/null
+++ b/tests/cts/permission/telephony/src/android/permission/cts/telephony/TelephonyManagerPermissionTest.java
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2009 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.permission.cts.telephony;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Test the non-location-related functionality of TelephonyManager.
+ */
+@RunWith(AndroidJUnit4.class)
+public class TelephonyManagerPermissionTest {
+
+ private boolean mHasTelephony;
+ TelephonyManager mTelephonyManager = null;
+ private AudioManager mAudioManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY);
+ mTelephonyManager =
+ (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ assertNotNull(mTelephonyManager);
+ mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+ assertNotNull(mAudioManager);
+ }
+
+ /**
+ * Verify that TelephonyManager.getDeviceId requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetDeviceId() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String id = mTelephonyManager.getDeviceId();
+ fail("Got device ID: " + id);
+ } catch (SecurityException e) {
+ // expected
+ }
+ try {
+ String id = mTelephonyManager.getDeviceId(0);
+ fail("Got device ID: " + id);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that TelephonyManager.getLine1Number requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetLine1Number() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String nmbr = mTelephonyManager.getLine1Number();
+ fail("Got line 1 number: " + nmbr);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that TelephonyManager.getSimSerialNumber requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetSimSerialNumber() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String nmbr = mTelephonyManager.getSimSerialNumber();
+ fail("Got SIM serial number: " + nmbr);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that TelephonyManager.getSubscriberId requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetSubscriberId() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String sid = mTelephonyManager.getSubscriberId();
+ fail("Got subscriber id: " + sid);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that TelephonyManager.getVoiceMailNumber requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testVoiceMailNumber() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String vmnum = mTelephonyManager.getVoiceMailNumber();
+ fail("Got voicemail number: " + vmnum);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+ /**
+ * Verify that AudioManager.setMode requires Permission.
+ * <p>
+ * Requires Permissions:
+ * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} and
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE} for
+ * {@link AudioManager#MODE_IN_CALL}.
+ */
+ @Test
+ public void testSetMode() {
+ if (!mHasTelephony) {
+ return;
+ }
+ int audioMode = mAudioManager.getMode();
+ mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+ assertEquals(audioMode, mAudioManager.getMode());
+ }
+
+ /**
+ * Tests that isManualNetworkSelectionAllowed requires permission
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testIsManualNetworkSelectionAllowedWithoutPermission() {
+ if (!mHasTelephony) {
+ return;
+ }
+ try {
+ mTelephonyManager.isManualNetworkSelectionAllowed();
+ fail("Expected SecurityException. App does not have carrier privileges.");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Tests that getManualNetworkSelectionPlmn requires permission
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testGetManualNetworkSelectionPlmnWithoutPermission() {
+ if (!mHasTelephony) {
+ return;
+ }
+ try {
+ mTelephonyManager.getManualNetworkSelectionPlmn();
+ fail("Expected SecurityException. App does not have carrier privileges.");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Verify that Telephony related broadcasts are protected.
+ */
+ @Test
+ public void testProtectedBroadcasts() {
+ if (!mHasTelephony) {
+ return;
+ }
+ try {
+ Intent intent = new Intent("android.intent.action.SIM_STATE_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.intent.action.SERVICE_STATE");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent(
+ "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.intent.action.SIG_STR");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ try {
+ Intent intent = new Intent("android.provider.Telephony.SECRET_CODE");
+ getContext().sendBroadcast(intent);
+ fail("SecurityException expected!");
+ } catch (SecurityException e) {}
+ }
+
+ /**
+ * Verify that TelephonyManager.getImei requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetImei() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String imei = mTelephonyManager.getImei();
+ fail("Got IMEI: " + imei);
+ } catch (SecurityException e) {
+ // expected
+ }
+ try {
+ String imei = mTelephonyManager.getImei(0);
+ fail("Got IMEI: " + imei);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that getNetworkType and getDataNetworkType requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void testGetNetworkType() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ mTelephonyManager.getNetworkType();
+ fail("getNetworkType did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+
+ try {
+ mTelephonyManager.getDataNetworkType();
+ fail("getDataNetworkType did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Tests that getNetworkSelectionMode requires permission
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testGetNetworkSelectionModeWithoutPermission() {
+ if (!mHasTelephony) {
+ return;
+ }
+ assertThrowsSecurityException(() -> mTelephonyManager.getNetworkSelectionMode(),
+ "Expected SecurityException. App does not have carrier privileges.");
+ }
+
+ /**
+ * Tests that setNetworkSelectionModeAutomatic requires permission
+ * Expects a security exception since the caller does not have carrier privileges.
+ */
+ @Test
+ public void testSetNetworkSelectionModeAutomaticWithoutPermission() {
+ if (!mHasTelephony) {
+ return;
+ }
+ assertThrowsSecurityException(() -> mTelephonyManager.setNetworkSelectionModeAutomatic(),
+ "Expected SecurityException. App does not have carrier privileges.");
+ }
+
+ /**
+ * Verify that setForbiddenPlmns requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ */
+ @Test
+ public void testSetForbiddenPlmns() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ mTelephonyManager.setForbiddenPlmns(new ArrayList<String>());
+ fail("SetForbiddenPlmns did not throw a SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ static final int PHONE_STATE_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
+ | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
+
+ static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
+ PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
+ | PhoneStateListener.LISTEN_BARRING_INFO;
+
+ static final int PHONE_PERMISSIONS_MASK =
+ PHONE_STATE_PERMISSION_MASK | PRECISE_PHONE_STATE_PERMISSION_MASK;
+
+ /**
+ * Verify the documented permissions for PhoneStateListener.
+ */
+ @Test
+ public void testListen() {
+ PhoneStateListener psl = new PhoneStateListener((Runnable r) -> { });
+
+ try {
+ for (int i = 1; i != 0; i = i << 1) {
+ if ((i & PHONE_PERMISSIONS_MASK) == 0) continue;
+ final int listenBit = i;
+ assertThrowsSecurityException(() -> mTelephonyManager.listen(psl, listenBit),
+ "Expected a security exception for " + Integer.toHexString(i));
+ }
+ } finally {
+ mTelephonyManager.listen(psl, PhoneStateListener.LISTEN_NONE);
+ }
+ }
+
+ private static Context getContext() {
+ return InstrumentationRegistry.getContext();
+ }
+
+ // An actual version of assertThrows() was added in JUnit5
+ private static <T extends Throwable> void assertThrows(Class<T> clazz, Runnable r,
+ String message) {
+ try {
+ r.run();
+ } catch (Exception expected) {
+ assertTrue(clazz.isAssignableFrom(expected.getClass()));
+ return;
+ }
+ fail(message);
+ }
+
+ private static void assertThrowsSecurityException(Runnable r, String message) {
+ assertThrows(SecurityException.class, r, message);
+ }
+
+ /**
+ * Verify that TelephonyManager.getPrimaryImei requires Permission.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}.
+ */
+ @Test
+ public void testGetPrimaryImei() {
+ if (!mHasTelephony) {
+ return;
+ }
+
+ try {
+ String primaryImei = mTelephonyManager.getPrimaryImei();
+ fail("Received Primary Imei value: " + primaryImei);
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ /**
+ * Verify that getCarrierRestrictionStatus requires permission
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE}.
+ */
+ @Test
+ public void getCarrierRestrictionStatus_Exception() {
+ if (!mHasTelephony) {
+ return;
+ }
+ LinkedBlockingQueue<Integer> carrierRestrictionStatusResult = new LinkedBlockingQueue<>(1);
+ try {
+ mTelephonyManager.getCarrierRestrictionStatus(getContext().getMainExecutor(),
+ carrierRestrictionStatusResult::offer);
+ // Test case fail, if the API don't catch the security exception.
+ fail();
+ } catch (SecurityException ex) {
+ // expecting the security exception.
+ } catch (Exception ex) {
+ // The test case should fail if other than security exception comes.
+ fail();
+ }
+ }
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/Android.bp
new file mode 100644
index 000000000..6f0bcf111
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAdversarialPermissionDefinerApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ certificate: ":cts-testkey1",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/AndroidManifest.xml
new file mode 100644
index 000000000..d28fba87c
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.AdversarialPermissionDefinerApp">
+
+ <permission android:name="android.permission.cts.revokepermissionwhenremoved.TestPermission"
+ android:protectionLevel="dangerous"
+ android:label="TestPermission"
+ android:description="@string/test_permission" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/res/values/strings.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/res/values/strings.xml
new file mode 100644
index 000000000..bfb3e1e2b
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionDefinerApp/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="test_permission">Test Permission</string>
+</resources>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/Android.bp
new file mode 100644
index 000000000..41f01e981
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAdversarialPermissionUserApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/AndroidManifest.xml
new file mode 100644
index 000000000..f514d549a
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/AdversarialPermissionUserApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.userapp">
+
+ <uses-permission android:name="android.permission.cts.revokepermissionwhenremoved.TestPermission" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/Android.bp
new file mode 100644
index 000000000..a3e1f13d2
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsInstallPermissionDefinerApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+ certificate: ":cts-testkey1",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/AndroidManifest.xml
new file mode 100644
index 000000000..2df67431b
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionDefinerApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.installpermissiondefinerapp">
+
+ <permission
+ android:name="android.permission.cts.revokepermissionwhenremoved.TestInstallPermission"
+ android:protectionLevel="normal" />
+
+ <application />
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/Android.bp
new file mode 100644
index 000000000..caaa8e898
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsInstallPermissionEscalatorApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+ certificate: ":cts-testkey1",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/AndroidManifest.xml
new file mode 100644
index 000000000..6320618c5
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionEscalatorApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.installpermissionescalatorapp">
+
+ <permission
+ android:name="android.permission.cts.revokepermissionwhenremoved.TestInstallPermission"
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="dangerous" />
+
+ <application />
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/Android.bp
new file mode 100644
index 000000000..d9ca4c8ea
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsInstallPermissionUserApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/AndroidManifest.xml
new file mode 100644
index 000000000..acfafa986
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstallPermissionUserApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.installpermissionuserapp">
+
+ <uses-permission android:name="android.permission.cts.revokepermissionwhenremoved.TestInstallPermission" />
+
+ <application />
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstalltimePermissionUserApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstalltimePermissionUserApp/AndroidManifest.xml
new file mode 100644
index 000000000..7a0e40554
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/InstalltimePermissionUserApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.installtimepermissionuserapp">
+
+ <uses-permission android:name="android.permission.cts.revokepermissionwhenremoved.TestInstalltimePermission" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/Android.bp
new file mode 100644
index 000000000..b4ea30ada
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRuntimePermissionDefinerApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+ certificate: ":cts-testkey1",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/AndroidManifest.xml
new file mode 100644
index 000000000..d3cf6d0aa
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.runtimepermissiondefinerapp">
+
+ <permission android:name="android.permission.cts.revokepermissionwhenremoved.TestRuntimePermission"
+ android:protectionLevel="dangerous"
+ android:label="TestPermission"
+ android:description="@string/test_permission" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/res/values/strings.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/res/values/strings.xml
new file mode 100644
index 000000000..bfb3e1e2b
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionDefinerApp/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="test_permission">Test Permission</string>
+</resources>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/Android.bp
new file mode 100644
index 000000000..22c6ccd6f
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRuntimePermissionUserApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ "sts",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/AndroidManifest.xml
new file mode 100644
index 000000000..d977e46e4
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/RuntimePermissionUserApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.runtimepermissionuserapp">
+
+ <uses-permission android:name="android.permission.cts.revokepermissionwhenremoved.TestRuntimePermission" />
+
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/Android.bp b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/Android.bp
new file mode 100644
index 000000000..5627a3d36
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsVictimPermissionDefinerApp",
+ defaults: ["cts_defaults"],
+ sdk_version: "current",
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ "mts-permission",
+ ],
+ certificate: ":cts-testkey1",
+}
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/AndroidManifest.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/AndroidManifest.xml
new file mode 100644
index 000000000..3fb0abd29
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permission.cts.revokepermissionwhenremoved.VictimPermissionDefinerApp">
+ <permission android:name="android.permission.cts.revokepermissionwhenremoved.TestPermission"
+ android:protectionLevel="signature"
+ android:label="Test Permission"
+ android:description="@string/test_permission" />
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/res/values/strings.xml b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/res/values/strings.xml
new file mode 100644
index 000000000..bfb3e1e2b
--- /dev/null
+++ b/tests/cts/permission/testapps/RevokePermissionWhenRemoved/VictimPermissionDefinerApp/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="test_permission">Test Permission</string>
+</resources>
diff --git a/tests/cts/permissionmultiuser/Android.bp b/tests/cts/permissionmultiuser/Android.bp
new file mode 100644
index 000000000..f577c82e3
--- /dev/null
+++ b/tests/cts/permissionmultiuser/Android.bp
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionMultiUserTestCases",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ min_sdk_version: "30",
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "Harrier",
+ "modules-utils-build_system",
+ "Nene",
+ ],
+ data: [
+ ":CtsRequestLocationApp",
+ ],
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/cts/permissionmultiuser/AndroidManifest.xml b/tests/cts/permissionmultiuser/AndroidManifest.xml
new file mode 100644
index 000000000..15bc3af34
--- /dev/null
+++ b/tests/cts/permissionmultiuser/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionmultiuser.cts">
+
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permissionmultiuser.cts"
+ android:label="CTS multi-user tests for permissions">
+ </instrumentation>
+</manifest>
diff --git a/tests/cts/permissionmultiuser/AndroidTest.xml b/tests/cts/permissionmultiuser/AndroidTest.xml
new file mode 100644
index 000000000..10fd4e7a5
--- /dev/null
+++ b/tests/cts/permissionmultiuser/AndroidTest.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<configuration description="Config for CTS permissionmultiuser test cases">
+
+ <option name="test-suite-tag" value="cts" />
+
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="multiuser" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" />
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionMultiUserTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="CtsRequestLocationApp.apk->/data/local/tmp/cts-permissionmultiuser/CtsRequestLocationApp.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="appops set android.permissionmultiuser.cts REQUEST_INSTALL_PACKAGES allow" />
+ <!-- disable DeprecatedAbi warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
+ </target_preparer>
+
+ <!-- Create place to store apks -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts-permissionmultiuser" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts-permissionmultiuser"/>
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permissionmultiuser.cts" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
+ <option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+
+</configuration>
diff --git a/tests/cts/permissionmultiuser/OWNERS b/tests/cts/permissionmultiuser/OWNERS
new file mode 100644
index 000000000..fb6099cf7
--- /dev/null
+++ b/tests/cts/permissionmultiuser/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/tests/cts/permissionmultiuser/RequestLocationApp/Android.bp b/tests/cts/permissionmultiuser/RequestLocationApp/Android.bp
new file mode 100644
index 000000000..d645e15d7
--- /dev/null
+++ b/tests/cts/permissionmultiuser/RequestLocationApp/Android.bp
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRequestLocationApp",
+ target_sdk_version: "30",
+ min_sdk_version: "30",
+}
diff --git a/tests/cts/permissionmultiuser/RequestLocationApp/AndroidManifest.xml b/tests/cts/permissionmultiuser/RequestLocationApp/AndroidManifest.xml
new file mode 100644
index 000000000..e5e7609eb
--- /dev/null
+++ b/tests/cts/permissionmultiuser/RequestLocationApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionmultiuser.cts.requestlocation">
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <application>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionmultiuser/TEST_MAPPING b/tests/cts/permissionmultiuser/TEST_MAPPING
new file mode 100644
index 000000000..48f5ef537
--- /dev/null
+++ b/tests/cts/permissionmultiuser/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsPermissionMultiUserTestCases"
+ }
+ ]
+}
diff --git a/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt
new file mode 100644
index 000000000..384dab861
--- /dev/null
+++ b/tests/cts/permissionmultiuser/src/android/permissionmultiuser/cts/AppDataSharingUpdatesTest.kt
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2023 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.permissionmultiuser.cts
+
+import android.app.Instrumentation
+import android.app.PendingIntent
+import android.app.PendingIntent.FLAG_MUTABLE
+import android.app.PendingIntent.FLAG_UPDATE_CURRENT
+import android.app.UiAutomation
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Context.RECEIVER_EXPORTED
+import android.content.Intent
+import android.content.Intent.ACTION_REVIEW_APP_DATA_SHARING_UPDATES
+import android.content.IntentFilter
+import android.content.pm.PackageInstaller
+import android.content.pm.PackageInstaller.EXTRA_STATUS
+import android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE
+import android.content.pm.PackageInstaller.STATUS_FAILURE_INVALID
+import android.content.pm.PackageInstaller.STATUS_SUCCESS
+import android.content.pm.PackageInstaller.SessionParams
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FEATURE_AUTOMOTIVE
+import android.content.pm.PackageManager.FEATURE_LEANBACK
+import android.os.Build
+import android.os.PersistableBundle
+import android.os.SystemClock
+import android.os.UserHandle
+import android.provider.DeviceConfig
+import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
+import android.support.test.uiautomator.By
+import android.support.test.uiautomator.BySelector
+import android.support.test.uiautomator.StaleObjectException
+import android.support.test.uiautomator.UiDevice
+import android.support.test.uiautomator.UiObject2
+import android.util.Log
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.bedstead.harrier.BedsteadJUnit4
+import com.android.bedstead.harrier.DeviceState
+import com.android.bedstead.harrier.annotations.EnsureHasPermission
+import com.android.bedstead.harrier.annotations.EnsureSecureSettingSet
+import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature
+import com.android.bedstead.harrier.annotations.RequireNotWatch
+import com.android.bedstead.harrier.annotations.RequireRunOnAdditionalUser
+import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile
+import com.android.bedstead.harrier.annotations.RequireSdkVersion
+import com.android.bedstead.nene.permissions.CommonPermissions.INTERACT_ACROSS_USERS
+import com.android.compatibility.common.util.ApiTest
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts
+import com.android.compatibility.common.util.UiAutomatorUtils
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.util.concurrent.LinkedBlockingQueue
+import java.util.concurrent.TimeUnit
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests the UI that displays information about apps' updates to their data sharing policies when
+ * device has multiple users.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@RequireSdkVersion(min = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+@RequireDoesNotHaveFeature(FEATURE_AUTOMOTIVE)
+@RequireDoesNotHaveFeature(FEATURE_LEANBACK)
+@RequireNotWatch(reason = "Data sharing update page is unavailable on watch")
+@RunWith(BedsteadJUnit4::class)
+@EnsureSecureSettingSet(key = "user_setup_complete", value = "1")
+class AppDataSharingUpdatesTest {
+
+ @get:Rule
+ val deviceConfigSafetyLabelChangeNotificationsEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED,
+ true.toString())
+
+ @get:Rule
+ val deviceConfigDataSharingUpdatesPeriod =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS,
+ "600000")
+
+ /**
+ * This rule serves to limit the max number of safety labels that can be persisted, so that
+ * repeated tests don't overwhelm the disk storage on the device.
+ */
+ @get:Rule
+ val deviceConfigMaxSafetyLabelsPersistedPerApp =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP,
+ "2")
+
+ @Before
+ fun registerInstallSessionResultReceiver() {
+ context.registerReceiver(
+ installSessionResultReceiver, IntentFilter(INSTALL_ACTION_CALLBACK), RECEIVER_EXPORTED)
+ }
+
+ @After
+ fun unregisterInstallSessionResultReceiver() {
+ try {
+ context.unregisterReceiver(installSessionResultReceiver)
+ } catch (ignored: IllegalArgumentException) {}
+ }
+
+ @Test
+ @EnsureHasPermission(INTERACT_ACROSS_USERS)
+ @RequireRunOnWorkProfile
+ @ApiTest(apis = ["android.content.Intent#ACTION_REVIEW_APP_DATA_SHARING_UPDATES"])
+ fun openDataSharingUpdatesPage_workProfile_whenAppHasUpdateAndLocationGranted_showUpdates() {
+ installPackageViaSession(LOCATION_PACKAGE_APK_PATH, createAppMetadataWithNoSharing())
+ waitForBroadcasts()
+ installPackageViaSession(
+ LOCATION_PACKAGE_APK_PATH, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+ grantLocationPermission(LOCATION_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivityForUser(deviceState.initialUser().userHandle())
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(LOCATION_PACKAGE_NAME_SUBSTRING), true)
+ } finally {
+ pressBack()
+ uninstallPackage(LOCATION_PACKAGE_NAME)
+ }
+ }
+
+ @Test
+ @EnsureHasPermission(INTERACT_ACROSS_USERS)
+ @RequireRunOnAdditionalUser
+ @ApiTest(apis = ["android.content.Intent#ACTION_REVIEW_APP_DATA_SHARING_UPDATES"])
+ fun openDataSharingUpdatesPage_additionalUser_whenAppHasUpdateAndLocationGranted_showUpdates() {
+ installPackageViaSession(LOCATION_PACKAGE_APK_PATH, createAppMetadataWithNoSharing())
+ waitForBroadcasts()
+ installPackageViaSession(
+ LOCATION_PACKAGE_APK_PATH, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+ grantLocationPermission(LOCATION_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivityForUser(deviceState.additionalUser().userHandle())
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(LOCATION_PACKAGE_NAME_SUBSTRING), true)
+ } finally {
+ pressBack()
+ uninstallPackage(LOCATION_PACKAGE_NAME)
+ }
+
+ deviceState.initialUser().switchTo()
+
+ startAppDataSharingUpdatesActivityForUser(deviceState.initialUser().userHandle())
+
+ try {
+ // Verify that state does not leak across users.
+ assertNoUpdatesPresent()
+ findView(By.textContains(LOCATION_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ /** Companion object for [AppDataSharingUpdatesTest]. */
+ companion object {
+ @JvmField @ClassRule @Rule val deviceState: DeviceState = DeviceState()
+
+ @JvmStatic
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = instrumentation.context
+ @JvmStatic private val uiAutomation: UiAutomation = instrumentation.uiAutomation
+ @JvmStatic private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
+ @JvmStatic private val packageManager: PackageManager = context.packageManager
+ @JvmStatic private val packageInstaller = packageManager.packageInstaller
+ private data class SessionResult(val status: Int?)
+ private val TAG = AppDataSharingUpdatesTest::class.simpleName
+
+ private const val APK_DIRECTORY = "/data/local/tmp/cts-permissionmultiuser"
+ private const val LOCATION_PACKAGE_NAME = "android.permissionmultiuser.cts.requestlocation"
+ private const val LOCATION_PACKAGE_APK_PATH = "CtsRequestLocationApp.apk"
+ private const val INSTALL_ACTION_CALLBACK = "AppDataSharingUpdatesTest.install_callback"
+ private const val PACKAGE_INSTALLER_TIMEOUT = 60000L
+ private const val IDLE_TIMEOUT_MILLIS: Long = 1000
+ private const val TIMEOUT_MILLIS: Long = 20000
+
+ private const val KEY_VERSION = "version"
+ private const val KEY_SAFETY_LABELS = "safety_labels"
+ private const val KEY_DATA_SHARED = "data_shared"
+ private const val KEY_DATA_LABELS = "data_labels"
+ private const val KEY_PURPOSES = "purposes"
+ private const val INITIAL_SAFETY_LABELS_VERSION = 1L
+ private const val INITIAL_TOP_LEVEL_VERSION = 1L
+ private const val LOCATION_CATEGORY = "location"
+ private const val APPROX_LOCATION = "approx_location"
+ private const val PURPOSE_FRAUD_PREVENTION_SECURITY = 4
+
+ private const val DATA_SHARING_UPDATES = "Data sharing updates for location"
+ private const val DATA_SHARING_UPDATES_SUBTITLE =
+ "These apps have changed the way they may share your location data. They may not" +
+ " have shared it before, or may now share it for advertising or marketing" +
+ " purposes."
+ private const val DATA_SHARING_NO_UPDATES_MESSAGE = "No updates at this time"
+ private const val UPDATES_IN_LAST_30_DAYS = "Updated within 30 days"
+ private const val DATA_SHARING_UPDATES_FOOTER_MESSAGE =
+ "The developers of these apps provided info about their data sharing practices" +
+ " to an app store. They may update it over time.\n\nData sharing" +
+ " practices may vary based on your app version, use, region, and age."
+ private const val LOCATION_PACKAGE_NAME_SUBSTRING = "android.permissionmultiuser"
+ private const val PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS =
+ "data_sharing_update_period_millis"
+ private const val PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP =
+ "max_safety_labels_persisted_per_app"
+
+ private var installSessionResult = LinkedBlockingQueue<SessionResult>()
+
+ private val installSessionResultReceiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val status = intent.getIntExtra(EXTRA_STATUS, STATUS_FAILURE_INVALID)
+ val msg = intent.getStringExtra(EXTRA_STATUS_MESSAGE)
+ Log.d(TAG, "status: $status, msg: $msg")
+
+ installSessionResult.offer(SessionResult(status))
+ }
+ }
+
+ /** Installs an app with the provided [appMetadata] */
+ private fun installPackageViaSession(
+ apkName: String,
+ appMetadata: PersistableBundle? = null,
+ packageSource: Int? = null
+ ) {
+ val session = createPackageInstallerSession(packageSource)
+ runWithShellPermissionIdentity {
+ writePackageInstallerSession(session, apkName)
+ if (appMetadata != null) {
+ setAppMetadata(session, appMetadata)
+ }
+ commitPackageInstallerSession(session)
+
+ // No need to click installer UI here due to running in shell permission identity
+ // and not needing user interaction to complete install.
+ // Install should have succeeded.
+ val result = getInstallSessionResult()
+ assertThat(result.status).isEqualTo(STATUS_SUCCESS)
+ }
+ }
+
+ private fun createPackageInstallerSession(
+ packageSource: Int? = null
+ ): PackageInstaller.Session {
+ val sessionParam = SessionParams(SessionParams.MODE_FULL_INSTALL)
+ if (packageSource != null) {
+ sessionParam.setPackageSource(packageSource)
+ }
+
+ val sessionId = packageInstaller.createSession(sessionParam)
+ return packageInstaller.openSession(sessionId)
+ }
+
+ private fun writePackageInstallerSession(
+ session: PackageInstaller.Session,
+ apkName: String
+ ) {
+ val apkFile = File(APK_DIRECTORY, apkName)
+ apkFile.inputStream().use { fileOnDisk ->
+ session
+ .openWrite(/* name= */ apkName, /* offsetBytes= */ 0, /* lengthBytes= */ -1)
+ .use { sessionFile -> fileOnDisk.copyTo(sessionFile) }
+ }
+ }
+
+ private fun commitPackageInstallerSession(session: PackageInstaller.Session) {
+ // PendingIntent that triggers a INSTALL_ACTION_CALLBACK broadcast that gets received by
+ // installSessionResultReceiver when install actions occur with this session
+ val installActionPendingIntent =
+ PendingIntent.getBroadcast(
+ context,
+ 0,
+ Intent(INSTALL_ACTION_CALLBACK).setPackage(context.packageName),
+ FLAG_UPDATE_CURRENT or FLAG_MUTABLE)
+ session.commit(installActionPendingIntent.intentSender)
+ }
+
+ private fun setAppMetadata(session: PackageInstaller.Session, data: PersistableBundle) {
+ try {
+ session.setAppMetadata(data)
+ } catch (e: Exception) {
+ session.abandon()
+ throw e
+ }
+ }
+
+ private fun getInstallSessionResult(
+ timeout: Long = PACKAGE_INSTALLER_TIMEOUT
+ ): SessionResult {
+ return installSessionResult.poll(timeout, TimeUnit.MILLISECONDS)
+ ?: SessionResult(null /* status */)
+ }
+
+ private fun uninstallPackage(packageName: String) {
+ runShellCommand("pm uninstall $packageName").trim()
+ }
+
+ private fun pressBack() {
+ uiDevice.pressBack()
+ uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
+ }
+
+ /** Returns an App Metadata [PersistableBundle] representation where no data is shared. */
+ private fun createAppMetadataWithNoSharing(): PersistableBundle {
+ return createMetadataWithDataShared(PersistableBundle())
+ }
+
+ /**
+ * Returns an App Metadata [PersistableBundle] representation where location data is shared,
+ * but not for advertising purpose.
+ */
+ private fun createAppMetadataWithLocationSharingNoAds(): PersistableBundle {
+ val locationBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(
+ APPROX_LOCATION,
+ PersistableBundle().apply {
+ putIntArray(
+ KEY_PURPOSES,
+ listOf(PURPOSE_FRAUD_PREVENTION_SECURITY).toIntArray())
+ })
+ }
+
+ val dataSharedBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(LOCATION_CATEGORY, locationBundle)
+ }
+
+ return createMetadataWithDataShared(dataSharedBundle)
+ }
+
+ /**
+ * Returns an App Metadata [PersistableBundle] representation where with the provided data
+ * shared.
+ */
+ private fun createMetadataWithDataShared(
+ dataSharedBundle: PersistableBundle
+ ): PersistableBundle {
+ val dataLabelBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(KEY_DATA_SHARED, dataSharedBundle)
+ }
+
+ val safetyLabelBundle =
+ PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION)
+ putPersistableBundle(KEY_DATA_LABELS, dataLabelBundle)
+ }
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, safetyLabelBundle)
+ }
+ }
+
+ /**
+ * Starts activity with intent [ACTION_REVIEW_APP_DATA_SHARING_UPDATES] for the provided
+ * user.
+ */
+ fun startAppDataSharingUpdatesActivityForUser(userHandle: UserHandle) {
+ runWithShellPermissionIdentity {
+ context.startActivityAsUser(
+ Intent(ACTION_REVIEW_APP_DATA_SHARING_UPDATES).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ },
+ userHandle)
+ }
+ }
+
+ private fun assertUpdatesPresent() {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_SUBTITLE), true)
+ findView(By.textContains(UPDATES_IN_LAST_30_DAYS), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_FOOTER_MESSAGE), true)
+ }
+
+ private fun assertNoUpdatesPresent() {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(DATA_SHARING_NO_UPDATES_MESSAGE), true)
+ findView(By.textContains(LOCATION_PACKAGE_NAME_SUBSTRING), false)
+ }
+
+ private fun grantLocationPermission(packageName: String) {
+ uiAutomation.grantRuntimePermission(
+ packageName, android.Manifest.permission.ACCESS_FINE_LOCATION)
+ }
+
+ protected fun waitFindObject(
+ selector: BySelector,
+ timeoutMillis: Long = 20_000L
+ ): UiObject2 {
+ uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
+ val startTime = SystemClock.elapsedRealtime()
+ return try {
+ UiAutomatorUtils.waitFindObject(selector, timeoutMillis)
+ } catch (e: StaleObjectException) {
+ val remainingTime = timeoutMillis - (SystemClock.elapsedRealtime() - startTime)
+ if (remainingTime <= 0) {
+ throw e
+ }
+ UiAutomatorUtils.waitFindObject(selector, remainingTime)
+ }
+ }
+
+ private fun findView(selector: BySelector, expected: Boolean) {
+ val timeoutMillis =
+ if (expected) {
+ 20000L
+ } else {
+ 1000L
+ }
+
+ val exception =
+ try {
+ uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
+ val startTime = SystemClock.elapsedRealtime()
+ try {
+ UiAutomatorUtils.waitFindObject(selector, timeoutMillis)
+ } catch (e: StaleObjectException) {
+ val remainingTime =
+ timeoutMillis - (SystemClock.elapsedRealtime() - startTime)
+ if (remainingTime <= 0) {
+ throw e
+ }
+ UiAutomatorUtils.waitFindObject(selector, remainingTime)
+ }
+ null
+ } catch (e: Exception) {
+ e
+ }
+ val actual = exception == null
+ val message = if (expected) {
+ "Expected view $selector not found"
+ } else {
+ "Unexpected view found: $selector"
+ }
+ Assert.assertTrue(message, actual == expected)
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/Android.bp b/tests/cts/permissionpolicy/Android.bp
new file mode 100644
index 000000000..5a92e890a
--- /dev/null
+++ b/tests/cts/permissionpolicy/Android.bp
@@ -0,0 +1,66 @@
+//
+// Copyright (C) 2009 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionPolicyTestCases",
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+ libs: ["android.test.base"],
+ static_libs: [
+ "androidx.test.core",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "guava",
+ "androidx.test.ext.junit-nodeps",
+ "truth-prebuilt",
+ "permission-test-util-lib",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ sdk_version: "test_current",
+ data: [
+ ":CtsLocationPermissionsUserSdk22",
+ ":CtsLocationPermissionsUserSdk29",
+ ":CtsSMSCallLogPermissionsUserSdk22",
+ ":CtsSMSCallLogPermissionsUserSdk29",
+ ":CtsStoragePermissionsUserDefaultSdk22",
+ ":CtsStoragePermissionsUserDefaultSdk28",
+ ":CtsStoragePermissionsUserDefaultSdk29",
+ ":CtsStoragePermissionsUserOptInSdk22",
+ ":CtsStoragePermissionsUserOptInSdk28",
+ ":CtsStoragePermissionsUserOptOutSdk29",
+ ":CtsStoragePermissionsPreservedUserOptOutSdk30",
+ ":CtsLegacyStorageNotIsolatedWithSharedUid",
+ ":CtsLegacyStorageIsolatedWithSharedUid",
+ ":CtsLegacyStorageRestrictedWithSharedUid",
+ ":CtsLegacyStorageRestrictedSdk28WithSharedUid",
+ ":CtsStoragePermissionsUserOptOutSdk30",
+ ":CtsSMSRestrictedWithSharedUid",
+ ":CtsSMSNotRestrictedWithSharedUid",
+ ":CtsProcessOutgoingCalls",
+ ],
+}
diff --git a/tests/cts/permissionpolicy/AndroidManifest.xml b/tests/cts/permissionpolicy/AndroidManifest.xml
new file mode 100755
index 000000000..53ddc59e5
--- /dev/null
+++ b/tests/cts/permissionpolicy/AndroidManifest.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts" android:targetSandboxVersion="2">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!--
+ This app contains tests to verify specialized permissions, that require the app to have
+ some permissions.
+ -->
+
+ <!-- need ability to send sms, to test that SMS's cannot be received -->
+ <uses-permission android:name="android.permission.SEND_SMS"/>
+
+ <!-- needs read phone numbers to get current phone number for R+ -->
+ <uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
+
+ <!-- needs read phone status to get current phone subscription info for R+ -->
+ <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+ <!-- need app that has WRITE_SETTINGS but not WRITE_SECURE_SETTINGS -->
+ <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
+
+ <!-- need app that has CALL_PHONE but not PROCESS_OUTGOING_CALL -->
+ <uses-permission android:name="android.permission.CALL_PHONE"/>
+
+ <!-- need app that has RECORD_AUDIO but not CAPTURE_AUDIO_OUTPUT -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+ <!-- need app that has READ_CONTACTS but not READ_PROFILE -->
+ <uses-permission android:name="android.permission.READ_CONTACTS"/>
+
+ <!-- need app that has WRITE_CONTACTS but not WRITE_PROFILE -->
+ <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+ <!-- need a permission that would ordinarily be granted, but has a maxSdkVersion that
+ causes it to be withheld under the current API level -->
+ <uses-permission
+ android:name="android.permission.INTERNET"
+ android:maxSdkVersion="18"/>
+
+
+ <!-- need a permission that will be granted -->
+ <uses-permission
+ android:name="android.permission.ACCESS_NETWORK_STATE"
+ android:maxSdkVersion="9000"/>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permissionpolicy.cts"
+ android:label="More CTS tests for permissions">
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/cts/permissionpolicy/AndroidTest.xml b/tests/cts/permissionpolicy/AndroidTest.xml
new file mode 100644
index 000000000..7fddaca52
--- /dev/null
+++ b/tests/cts/permissionpolicy/AndroidTest.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+<configuration description="Config for CTS Permission Policy test cases">
+
+ <option name="test-suite-tag" value="cts" />
+ <option name="not-shardable" value="true" />
+
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user"/>
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+ <option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
+
+ <!-- TODO(b/245579250): update to Sdk34 once sdk finalized -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk33ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionPolicyTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ </target_preparer>
+
+ <!-- Create place to store apks -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts-permissionpolicy" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts-permissionpolicy-permissionpolicy"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="CtsLocationPermissionsUserSdk22.apk->/data/local/tmp/cts-permissionpolicy/CtsLocationPermissionsUserSdk22.apk" />
+ <option name="push" value="CtsLocationPermissionsUserSdk29.apk->/data/local/tmp/cts-permissionpolicy/CtsLocationPermissionsUserSdk29.apk" />
+ <option name="push" value="CtsSMSCallLogPermissionsUserSdk22.apk->/data/local/tmp/cts-permissionpolicy/CtsSMSCallLogPermissionsUserSdk22.apk" />
+ <option name="push" value="CtsSMSCallLogPermissionsUserSdk29.apk->/data/local/tmp/cts-permissionpolicy/CtsSMSCallLogPermissionsUserSdk29.apk" />
+ <option name="push" value="CtsStoragePermissionsUserDefaultSdk22.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk22.apk" />
+ <option name="push" value="CtsStoragePermissionsUserDefaultSdk28.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk28.apk" />
+ <option name="push" value="CtsStoragePermissionsUserDefaultSdk29.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk29.apk" />
+ <option name="push" value="CtsStoragePermissionsUserOptInSdk22.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptInSdk22.apk" />
+ <option name="push" value="CtsStoragePermissionsUserOptInSdk28.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptInSdk28.apk" />
+ <option name="push" value="CtsStoragePermissionsUserOptOutSdk29.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptOutSdk29.apk" />
+ <option name="push" value="CtsLegacyStorageNotIsolatedWithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid.apk" />
+ <option name="push" value="CtsLegacyStorageIsolatedWithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid.apk" />
+ <option name="push" value="CtsLegacyStorageRestrictedWithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid.apk" />
+ <option name="push" value="CtsLegacyStorageRestrictedSdk28WithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid.apk" />
+ <option name="push" value="CtsStoragePermissionsUserOptOutSdk30.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptOutSdk30.apk" />
+ <option name="push" value="CtsStoragePermissionsPreservedUserOptOutSdk30.apk->/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30.apk" />
+ <option name="push" value="CtsSMSRestrictedWithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsSMSRestrictedWithSharedUid.apk" />
+ <option name="push" value="CtsSMSNotRestrictedWithSharedUid.apk->/data/local/tmp/cts-permissionpolicy/CtsSMSNotRestrictedWithSharedUid.apk" />
+ <option name="push" value="CtsProcessOutgoingCalls.apk->/data/local/tmp/cts-permissionpolicy/CtsProcessOutgoingCalls.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- disable DeprecatedAbi warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permissionpolicy.cts" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+
+</configuration>
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/Android.bp
new file mode 100644
index 000000000..146bdceae
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLegacyStorageIsolatedWithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..d221b1284
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageIsolatedWithSharedUid/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.legacystoragewithshareduid.isolated"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application android:label="CtsLegacyStorageIsolatedWithSharedUid" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/Android.bp
new file mode 100644
index 000000000..c4bc761ce
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLegacyStorageNotIsolatedWithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..69188d392
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageNotIsolatedWithSharedUid/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.legacystoragewithshareduid.notisolated"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+
+ <application android:label="CtsLegacyStorageNotIsolatedWithSharedUid"
+ android:requestLegacyExternalStorage="true" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/Android.bp
new file mode 100644
index 000000000..2373fc1e2
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLegacyStorageRestrictedSdk28WithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..cf09f33a3
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedSdk28WithSharedUid/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.legacystoragewithshareduid.restrictedsdk28"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application android:label="CtsLegacyStorageRestrictedSdk28WithSharedUid" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/Android.bp
new file mode 100644
index 000000000..523f74224
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLegacyStorageRestrictedWithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..3e9acc9aa
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLegacyStorageRestrictedWithSharedUid/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.legacystoragewithshareduid.restricted"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application android:label="CtsLegacyStorageRestrictedWithSharedUid" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/Android.bp b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/Android.bp
new file mode 100644
index 000000000..787cbaebe
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLocationPermissionsUserSdk22",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // TODO: Uncomment when uncommenting the test
+ // srcs: ["src/**/*.java"]
+
+}
diff --git a/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/AndroidManifest.xml
new file mode 100644
index 000000000..f0732755f
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk22/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22"/>
+
+ <application android:label="CtsLocationPermissionsUserSdk22">
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/Android.bp b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/Android.bp
new file mode 100644
index 000000000..93c8b72b3
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsLocationPermissionsUserSdk29",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // TODO: Uncomment when uncommenting the test
+ // srcs: ["src/**/*.java"]
+
+}
diff --git a/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/AndroidManifest.xml
new file mode 100644
index 000000000..21c73cc07
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsLocationPermissionsUserSdk29/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <application android:label="CtsLocationPermissionsUserSdk29">
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/Android.bp b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/Android.bp
new file mode 100644
index 000000000..ef6f44b5a
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsProcessOutgoingCalls",
+ defaults: ["cts_defaults"],
+ sdk_version: "test_current",
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+}
diff --git a/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/AndroidManifest.xml
new file mode 100644
index 000000000..254d7d9ce
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.receivecallbroadcast">
+
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <application>
+ <activity android:name=".ProcessOutgoingCallReceiver$BaseActivity" android:exported="true"/>
+ <receiver android:name=".ProcessOutgoingCallReceiver" android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
+ </intent-filter>
+ </receiver>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/src/android/permissionpolicy/cts/receivecallbroadcast/ProcessOutgoingCallReceiver.kt b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/src/android/permissionpolicy/cts/receivecallbroadcast/ProcessOutgoingCallReceiver.kt
new file mode 100644
index 000000000..fbab4a2d7
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsProcessOutgoingCalls/src/android/permissionpolicy/cts/receivecallbroadcast/ProcessOutgoingCallReceiver.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 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.permissionpolicy.cts.receivecallbroadcast
+
+import android.app.Activity
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+
+class ProcessOutgoingCallReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ context!!.sendBroadcast(Intent(ACTION_TEST_APP_RECEIVED_OUTGOING_CALL).setPackage(
+ TEST_CLASS_PKG_NAME))
+ }
+
+ class BaseActivity : Activity()
+}
+
+const val TEST_CLASS_PKG_NAME = "android.permissionpolicy.cts"
+const val ACTION_TEST_APP_RECEIVED_OUTGOING_CALL =
+ "android.permissionpolicy.cts.TEST_APP_RECEIVED_CALL"
diff --git a/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/Android.bp b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/Android.bp
new file mode 100644
index 000000000..b864a4e26
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsSMSCallLogPermissionsUserSdk22",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // TODO: Uncomment when uncommenting the test
+ // srcs: ["src/**/*.java"]
+
+}
diff --git a/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/AndroidManifest.xml
new file mode 100644
index 000000000..3d1207360
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk22/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.READ_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
+ <uses-permission android:name="android.permission.RECEIVE_MMS" />
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
+
+ <!-- CallLog -->
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22"/>
+
+ <application android:label="CtsSMSCallLogPermissionsUserSdk22">
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/Android.bp b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/Android.bp
new file mode 100644
index 000000000..d3a2e30f0
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsSMSCallLogPermissionsUserSdk29",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+
+ // TODO: Uncomment when uncommenting the test
+ // srcs: ["src/**/*.java"]
+
+}
diff --git a/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/AndroidManifest.xml
new file mode 100644
index 000000000..035e2e495
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSCallLogPermissionsUserSdk29/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.READ_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
+ <uses-permission android:name="android.permission.RECEIVE_MMS" />
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
+
+ <!-- CallLog -->
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <application android:label="CtsSMSCallLogPermissionsUserSdk29">
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/Android.bp
new file mode 100644
index 000000000..ab90dba35
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsSMSNotRestrictedWithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..109a9e8df
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSNotRestrictedWithSharedUid/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.smswithshareduid.notrestricted"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-permission android:name="android.permission.READ_SMS" />
+
+ <application android:label="CtsSMSNotRestrictedWithSharedUid" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/Android.bp b/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/Android.bp
new file mode 100644
index 000000000..8820ab776
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsSMSRestrictedWithSharedUid",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/AndroidManifest.xml
new file mode 100644
index 000000000..cb44afdd1
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsSMSRestrictedWithSharedUid/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.smswithshareduid.restricted"
+ android:versionCode="1"
+ android:sharedUserId="android.permissionpolicy.cts.restrictedpermissionuser.shareduid">
+
+ <uses-permission android:name="android.permission.READ_SMS" />
+
+ <application android:label="CtsSMSRestrictedWithSharedUid" />
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/Android.bp
new file mode 100644
index 000000000..6c76c7485
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsPreservedUserOptOutSdk30",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/AndroidManifest.xml
new file mode 100644
index 000000000..48c4f37c9
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:targetSdkVersion="30"/>
+
+ <application android:label="CtsStoragePermissionsPreservedUserOptOutSdk30"
+ android:preserveLegacyExternalStorage="true"/>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/Android.bp
new file mode 100644
index 000000000..bb817f780
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserDefaultSdk22",
+ defaults: ["cts_defaults"],
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/AndroidManifest.xml
new file mode 100644
index 000000000..543b9ebb8
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk22/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22"/>
+
+ <application android:label="CtsStoragePermissionsUserDefaultSdk22" />
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/Android.bp
new file mode 100644
index 000000000..60cb316f6
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserDefaultSdk28",
+ defaults: ["cts_defaults"],
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/AndroidManifest.xml
new file mode 100644
index 000000000..77920de15
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk28/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28"/>
+
+ <application android:label="CtsStoragePermissionsUserDefaultSdk28" />
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/Android.bp
new file mode 100644
index 000000000..d3d016a63
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserDefaultSdk29",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "29",
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/AndroidManifest.xml
new file mode 100644
index 000000000..e96452fd2
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk29/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:targetSdkVersion="29"/>
+
+ <application android:label="CtsStoragePermissionsUserDefaultSdk29" />
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/Android.bp
new file mode 100644
index 000000000..751342e2f
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserOptOutSdk30",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/AndroidManifest.xml
new file mode 100644
index 000000000..b5c71b373
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserDefaultSdk30/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:targetSdkVersion="30"/>
+
+ <application android:label="CtsStoragePermissionsUserOptOutSdk30"
+ android:requestLegacyExternalStorage="true"/>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/Android.bp
new file mode 100644
index 000000000..21e6aceef
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserOptInSdk22",
+ defaults: ["cts_defaults"],
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/AndroidManifest.xml
new file mode 100644
index 000000000..466d60157
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk22/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22"/>
+
+ <application android:label="CtsStoragePermissionsUserOptInSdk22"
+ android:requestLegacyExternalStorage="false"/>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/Android.bp
new file mode 100644
index 000000000..c7f30a8b6
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserOptInSdk28",
+ defaults: ["cts_defaults"],
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/AndroidManifest.xml
new file mode 100644
index 000000000..151bbbfea
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptInSdk28/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28"/>
+
+ <application android:label="CtsStoragePermissionsUserOptInSdk28"
+ android:requestLegacyExternalStorage="false"/>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/Android.bp b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/Android.bp
new file mode 100644
index 000000000..8ad13f798
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsStoragePermissionsUserOptOutSdk29",
+ defaults: ["cts_defaults"],
+
+ sdk_version: "current",
+}
diff --git a/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/AndroidManifest.xml b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/AndroidManifest.xml
new file mode 100644
index 000000000..e41ee7759
--- /dev/null
+++ b/tests/cts/permissionpolicy/CtsStoragePermissionsUserOptOutSdk29/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionpolicy.cts.restrictedpermissionuser"
+ android:versionCode="1">
+
+ <!-- Storage -->
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="29"/>
+
+ <application android:label="CtsStoragePermissionsUserOptOutSdk29"
+ android:requestLegacyExternalStorage="true"/>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/OWNERS b/tests/cts/permissionpolicy/OWNERS
new file mode 100644
index 000000000..395269207
--- /dev/null
+++ b/tests/cts/permissionpolicy/OWNERS
@@ -0,0 +1,7 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
+
+per-file NoLocationPermissionTest.java = tgunn@google.com
+per-file RestrictedStoragePermissionSharedUidTest.java = nandana@google.com
+per-file RestrictedStoragePermissionTest.java = nandana@google.com
diff --git a/tests/cts/permissionpolicy/res/raw/OWNERS b/tests/cts/permissionpolicy/res/raw/OWNERS
new file mode 100644
index 000000000..6e1a91b88
--- /dev/null
+++ b/tests/cts/permissionpolicy/res/raw/OWNERS
@@ -0,0 +1,8 @@
+hackbod@google.com
+patb@google.com
+yamasani@google.com
+michaelwr@google.com
+narayan@google.com
+roosa@google.com
+per-file automotive_android_manifest.xml = skeys@google.com
+per-file automotive_android_manifest.xml = file:platform/packages/services/Car:/OWNERS
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
new file mode 100644
index 000000000..46c5de140
--- /dev/null
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -0,0 +1,8082 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/AndroidManifest.xml
+**
+** Copyright 2006, 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.
+*/
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" coreApp="true" android:sharedUserId="android.uid.system"
+ android:sharedUserLabel="@string/android_system_label">
+
+ <!-- ================================================ -->
+ <!-- Special broadcasts that only the system can send -->
+ <!-- ================================================ -->
+ <eat-comment />
+
+ <protected-broadcast android:name="android.intent.action.SCREEN_OFF" />
+ <protected-broadcast android:name="android.intent.action.SCREEN_ON" />
+ <protected-broadcast android:name="android.intent.action.USER_PRESENT" />
+ <protected-broadcast android:name="android.intent.action.TIME_SET" />
+ <protected-broadcast android:name="android.intent.action.TIME_TICK" />
+ <protected-broadcast android:name="android.intent.action.TIMEZONE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.DATE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.PRE_BOOT_COMPLETED" />
+ <protected-broadcast android:name="android.intent.action.BOOT_COMPLETED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_INSTALL" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_ADDED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_REPLACED" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_REPLACED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED_INTERNAL" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_LOADED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_ENABLE_ROLLBACK" />
+ <protected-broadcast android:name="android.intent.action.CANCEL_ENABLE_ROLLBACK" />
+ <protected-broadcast android:name="android.intent.action.ROLLBACK_COMMITTED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENSION_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY" />
+ <protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.UID_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
+ <protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.SPLIT_CONFIGURATION_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.APPLICATION_LOCALE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.BATTERY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.BATTERY_LEVEL_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.BATTERY_LOW" />
+ <protected-broadcast android:name="android.intent.action.BATTERY_OKAY" />
+ <protected-broadcast android:name="android.intent.action.ACTION_POWER_CONNECTED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_SHUTDOWN" />
+ <protected-broadcast android:name="android.intent.action.CHARGING" />
+ <protected-broadcast android:name="android.intent.action.DISCHARGING" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_LOW" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_OK" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_FULL" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_STORAGE_NOT_FULL" />
+ <protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
+ <protected-broadcast android:name="android.intent.action.REBOOT" />
+ <protected-broadcast android:name="android.intent.action.DOCK_EVENT" />
+ <protected-broadcast android:name="android.intent.action.THERMAL_EVENT" />
+ <protected-broadcast android:name="android.intent.action.MASTER_CLEAR_NOTIFICATION" />
+ <protected-broadcast android:name="android.intent.action.USER_ADDED" />
+ <protected-broadcast android:name="android.intent.action.USER_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.USER_STARTING" />
+ <protected-broadcast android:name="android.intent.action.USER_STARTED" />
+ <protected-broadcast android:name="android.intent.action.USER_STOPPING" />
+ <protected-broadcast android:name="android.intent.action.USER_STOPPED" />
+ <protected-broadcast android:name="android.intent.action.USER_BACKGROUND" />
+ <protected-broadcast android:name="android.intent.action.USER_FOREGROUND" />
+ <protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
+ <protected-broadcast android:name="android.intent.action.USER_INITIALIZE" />
+ <protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
+ <protected-broadcast android:name="android.intent.action.DOMAINS_NEED_VERIFICATION" />
+ <protected-broadcast android:name="android.intent.action.OVERLAY_ADDED" />
+ <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
+
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
+ <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
+ <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_ENABLED_CHANGED" />
+ <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_POLICY_CHANGED" />
+ <protected-broadcast android:name="android.os.action.LOW_POWER_STANDBY_PORTS_CHANGED" />
+ <protected-broadcast android:name="android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED" />
+
+ <!-- @deprecated This is rarely used and will be phased out soon. -->
+ <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
+
+ <protected-broadcast android:name="android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL" />
+
+ <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE" />
+ <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
+ <protected-broadcast android:name="android.app.action.ENTER_CAR_MODE_PRIORITIZED" />
+ <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE_PRIORITIZED" />
+ <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
+ <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" />
+ <protected-broadcast android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
+
+ <protected-broadcast android:name="android.app.action.USER_ADDED" />
+ <protected-broadcast android:name="android.app.action.USER_REMOVED" />
+ <protected-broadcast android:name="android.app.action.USER_STARTED" />
+ <protected-broadcast android:name="android.app.action.USER_STOPPED" />
+ <protected-broadcast android:name="android.app.action.USER_SWITCHED" />
+
+ <protected-broadcast android:name="android.app.action.BUGREPORT_SHARING_DECLINED" />
+ <protected-broadcast android:name="android.app.action.BUGREPORT_FAILED" />
+ <protected-broadcast android:name="android.app.action.BUGREPORT_SHARE" />
+ <protected-broadcast android:name="android.app.action.SHOW_DEVICE_MONITORING_DIALOG" />
+ <protected-broadcast android:name="android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.INCIDENT_REPORT_READY" />
+
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DISABLED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_ENABLED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_HOST_RESTORED" />
+ <protected-broadcast android:name="android.appwidget.action.APPWIDGET_RESTORED" />
+
+ <protected-broadcast android:name="android.os.action.SETTING_RESTORED" />
+
+ <protected-broadcast android:name="android.app.backup.intent.CLEAR" />
+ <protected-broadcast android:name="android.app.backup.intent.INIT" />
+
+ <protected-broadcast android:name="android.bluetooth.intent.DISCOVERABLE_TIMEOUT" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.SCAN_MODE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.DISCOVERY_STARTED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.DISCOVERY_FINISHED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.LOCAL_NAME_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.UUID" />
+ <protected-broadcast android:name="android.bluetooth.device.action.MAS_INSTANCE" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ALIAS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
+ <protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.NAME_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.NAME_FAILED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
+ <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
+ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REPLY" />
+ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL" />
+ <protected-broadcast android:name="android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST" />
+ <protected-broadcast android:name="android.bluetooth.device.action.SDP_RECORD" />
+ <protected-broadcast android:name="android.bluetooth.device.action.BATTERY_LEVEL_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.devicepicker.action.LAUNCH" />
+ <protected-broadcast android:name="android.bluetooth.devicepicker.action.DEVICE_SELECTED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
+ <protected-broadcast
+ android:name="android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+ <protected-broadcast
+ android:name="android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.hearingaid.profile.action.PLAYING_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_DEVICE_AVAILABLE" />
+ <protected-broadcast android:name="android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE" />
+ <protected-broadcast
+ android:name="android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp.profile.action.CODEC_CONFIG_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.avrcp-controller.profile.action.BROWSE_CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.avrcp-controller.profile.action.FOLDER_LIST" />
+ <protected-broadcast
+ android:name="android.bluetooth.avrcp-controller.profile.action.TRACK_EVENT" />
+ <protected-broadcast
+ android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.input.profile.action.IDLE_TIME_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.input.profile.action.VIRTUAL_UNPLUG_STATUS" />
+ <protected-broadcast
+ android:name="android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_READ_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.mapmce.profile.action.MESSAGE_DELETED_STATUS_CHANGED" />
+ <protected-broadcast
+ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
+ <protected-broadcast
+ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
+ <protected-broadcast
+ android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONF_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_NODE_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_GROUP_STATUS_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.btopp.intent.action.INCOMING_FILE_NOTIFICATION" />
+ <protected-broadcast android:name="android.btopp.intent.action.USER_CONFIRMATION_TIMEOUT" />
+ <protected-broadcast android:name="android.btopp.intent.action.LIST" />
+ <protected-broadcast android:name="android.btopp.intent.action.OPEN_OUTBOUND" />
+ <protected-broadcast android:name="android.btopp.intent.action.HIDE_COMPLETE" />
+ <protected-broadcast android:name="android.btopp.intent.action.CONFIRM" />
+ <protected-broadcast android:name="android.btopp.intent.action.HIDE" />
+ <protected-broadcast android:name="android.btopp.intent.action.RETRY" />
+ <protected-broadcast android:name="android.btopp.intent.action.OPEN" />
+ <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
+ <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
+ <protected-broadcast android:name="android.btopp.intent.action.ACCEPT" />
+ <protected-broadcast android:name="android.btopp.intent.action.DECLINE" />
+ <protected-broadcast android:name="com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN" />
+ <protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
+ <protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
+ <protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
+ <protected-broadcast android:name="com.android.bluetooth.pbap.authcancelled" />
+ <protected-broadcast android:name="com.android.bluetooth.sap.USER_CONFIRM_TIMEOUT" />
+ <protected-broadcast android:name="com.android.bluetooth.sap.action.DISCONNECT_ACTION" />
+
+ <protected-broadcast android:name="android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED" />
+
+ <protected-broadcast android:name="android.hardware.usb.action.USB_STATE" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_PORT_CHANGED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
+ <protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
+
+ <protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
+ <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
+ <protected-broadcast android:name="android.media.action.MICROPHONE_MUTE_CHANGED" />
+ <protected-broadcast android:name="android.media.action.SPEAKERPHONE_STATE_CHANGED" />
+
+ <protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
+ <protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
+ <protected-broadcast android:name="android.media.VIBRATE_SETTING_CHANGED" />
+ <protected-broadcast android:name="android.media.VOLUME_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.MASTER_VOLUME_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.MASTER_MUTE_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.MASTER_MONO_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.MASTER_BALANCE_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.SCO_AUDIO_STATE_CHANGED" />
+ <protected-broadcast android:name="android.media.ACTION_SCO_AUDIO_STATE_UPDATED" />
+
+ <protected-broadcast android:name="android.intent.action.MEDIA_REMOVED" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_UNMOUNTED" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_CHECKING" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_NOFS" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_MOUNTED" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_SHARED" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_UNSHARED" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_BAD_REMOVAL" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_UNMOUNTABLE" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_EJECT" />
+
+ <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL" />
+ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
+ <!-- @deprecated. Only {@link android.net.ConnectivityManager.CONNECTIVITY_ACTION} is sent. -->
+ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
+ <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
+ <protected-broadcast android:name="android.net.conn.RESTRICT_BACKGROUND_CHANGED" />
+ <protected-broadcast android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
+ <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED" />
+
+ <protected-broadcast android:name="android.net.nsd.STATE_CHANGED" />
+
+ <!-- For OMAPI -->
+ <protected-broadcast android:name="android.se.omapi.action.SECURE_ELEMENT_STATE_CHANGED" />
+
+ <protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.nfc.action.PREFERRED_PAYMENT_CHANGED" />
+ <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
+ <protected-broadcast android:name="android.nfc.action.REQUIRE_UNLOCK_FOR_NFC" />
+ <protected-broadcast android:name="com.android.nfc.action.LLCP_UP" />
+ <protected-broadcast android:name="com.android.nfc.action.LLCP_DOWN" />
+ <protected-broadcast android:name="com.android.nfc.cardemulation.action.CLOSE_TAP_DIALOG" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.ALLOW_CONNECT" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.DENY_CONNECT" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.TIMEOUT_CONNECT" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
+ <protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
+ <!-- For NFC to BT handover -->
+ <protected-broadcast android:name="android.btopp.intent.action.WHITELIST_DEVICE" />
+ <protected-broadcast android:name="android.btopp.intent.action.STOP_HANDOVER_TRANSFER" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_SEND" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_SEND_MULTIPLE" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER" />
+
+ <protected-broadcast android:name="android.net.action.CLEAR_DNS_CACHE" />
+ <protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
+
+ <protected-broadcast android:name="android.os.UpdateLock.UPDATE_LOCK_CHANGED" />
+
+ <protected-broadcast android:name="android.intent.action.DREAMING_STARTED" />
+ <protected-broadcast android:name="android.intent.action.DREAMING_STOPPED" />
+ <protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+
+ <protected-broadcast android:name="com.android.server.stats.action.TRIGGER_COLLECTION" />
+
+ <protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
+ <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
+ <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
+ <protected-broadcast android:name="com.android.internal.action.EUICC_FACTORY_RESET" />
+ <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
+ <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
+ <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
+ <protected-broadcast android:name="com.android.server.net.action.SNOOZE_RAPID" />
+ <protected-broadcast android:name="com.android.server.wifi.ACTION_SHOW_SET_RANDOMIZATION_DETAILS" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_ALLOWED_APP" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_DISALLOWED_APP" />
+ <protected-broadcast android:name="com.android.server.wifi.action.NetworkSuggestion.USER_DISMISSED" />
+ <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_ALLOWED_CARRIER" />
+ <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_DISALLOWED_CARRIER" />
+ <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED" />
+ <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
+ <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
+ <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
+ <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE" />
+ <protected-broadcast android:name="com.android.server.wifi.wakeup.DISMISS_NOTIFICATION" />
+ <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_PREFERENCES" />
+ <protected-broadcast android:name="com.android.server.wifi.wakeup.OPEN_WIFI_SETTINGS" />
+ <protected-broadcast android:name="com.android.server.wifi.wakeup.TURN_OFF_WIFI_WAKE" />
+ <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
+ <protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.LINK_CONFIGURATION_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.CONFIGURED_NETWORKS_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.action.NETWORK_SETTINGS_RESET" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_ICON" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
+ <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
+ <protected-broadcast android:name="android.net.wifi.action.REFRESH_USER_PROVISIONING" />
+ <protected-broadcast android:name="android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION" />
+ <protected-broadcast android:name="android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.p2p.DISCOVERY_STATE_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.p2p.THIS_DEVICE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.p2p.PEERS_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.p2p.CONNECTION_STATE_CHANGE" />
+ <protected-broadcast android:name="android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED" />
+ <protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" />
+ <!-- This broadcast is no longer sent in S but it should stay protected to avoid third party
+ apps broadcasting this and confusing old system apps that may not have been updated. -->
+ <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
+ <protected-broadcast
+ android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
+ <protected-broadcast android:name="android.net.scoring.SCORE_NETWORKS" />
+ <protected-broadcast android:name="android.net.scoring.SCORER_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
+ <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE" />
+ <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
+ <protected-broadcast android:name="android.intent.action.ADVANCED_SETTINGS" />
+ <protected-broadcast android:name="android.intent.action.APPLICATION_RESTRICTIONS_CHANGED" />
+ <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES" />
+ <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT" />
+ <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_STATUS" />
+
+ <!-- Legacy -->
+ <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
+ <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_END" />
+
+ <protected-broadcast android:name="com.android.server.ACTION_TRIGGER_IDLE" />
+
+ <protected-broadcast android:name="android.intent.action.HDMI_PLUGGED" />
+
+ <protected-broadcast android:name="android.intent.action.PHONE_STATE" />
+
+ <protected-broadcast android:name="android.intent.action.SUB_DEFAULT_CHANGED" />
+
+ <protected-broadcast android:name="android.location.PROVIDERS_CHANGED" />
+ <protected-broadcast android:name="android.location.MODE_CHANGED" />
+ <protected-broadcast android:name="android.location.action.GNSS_CAPABILITIES_CHANGED" />
+
+ <protected-broadcast android:name="android.net.proxy.PAC_REFRESH" />
+
+ <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
+ <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
+ <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_CREATED" />
+ <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_LOST" />
+ <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
+ <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
+
+ <protected-broadcast
+ android:name="com.android.server.connectivityservice.CONNECTED_TO_PROVISIONING_NETWORK_ACTION" />
+
+ <!-- Defined in RestrictionsManager -->
+ <protected-broadcast
+ android:name="android.intent.action.PERMISSION_RESPONSE_RECEIVED" />
+ <!-- Defined in RestrictionsManager -->
+
+ <protected-broadcast android:name="android.intent.action.REQUEST_PERMISSION" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_STARTED" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_DONE" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_PROGRESS" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.TRANSFER_DONE" />
+
+ <protected-broadcast android:name="android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED" />
+
+ <protected-broadcast android:name="android.intent.action.ACTION_SET_RADIO_CAPABILITY_DONE" />
+ <protected-broadcast android:name="android.intent.action.ACTION_SET_RADIO_CAPABILITY_FAILED" />
+
+ <protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" />
+ <protected-broadcast android:name="android.app.action.SYSTEM_UPDATE_POLICY_CHANGED" />
+ <protected-broadcast android:name="android.app.action.RESET_PROTECTION_POLICY_CHANGED" />
+ <protected-broadcast android:name="android.app.action.DEVICE_OWNER_CHANGED" />
+ <protected-broadcast android:name="android.app.action.MANAGED_USER_CREATED" />
+
+ <!-- Added in N -->
+ <protected-broadcast android:name="android.intent.action.ANR" />
+ <protected-broadcast android:name="android.intent.action.CALL" />
+ <protected-broadcast android:name="android.intent.action.CALL_PRIVILEGED" />
+ <protected-broadcast android:name="android.intent.action.DROPBOX_ENTRY_ADDED" />
+ <protected-broadcast android:name="android.intent.action.INPUT_METHOD_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.internal_sim_state_changed" />
+ <protected-broadcast android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
+ <protected-broadcast android:name="android.intent.action.PRECISE_CALL_STATE" />
+ <protected-broadcast android:name="android.intent.action.SUBSCRIPTION_PHONE_STATE" />
+ <protected-broadcast android:name="android.intent.action.USER_INFO_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.USER_UNLOCKED" />
+ <protected-broadcast android:name="android.intent.action.WALLPAPER_CHANGED" />
+
+ <protected-broadcast android:name="android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS" />
+ <protected-broadcast android:name="android.app.action.DEVICE_ADMIN_DISABLED" />
+ <protected-broadcast android:name="android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED" />
+ <protected-broadcast android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ <protected-broadcast android:name="android.app.action.LOCK_TASK_ENTERING" />
+ <protected-broadcast android:name="android.app.action.LOCK_TASK_EXITING" />
+ <protected-broadcast android:name="android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE" />
+ <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_CHANGED" />
+ <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_EXPIRING" />
+ <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
+ <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
+ <protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+ <protected-broadcast android:name="com.android.server.ACTION_PROFILE_OFF_DEADLINE" />
+ <protected-broadcast android:name="com.android.server.ACTION_TURN_PROFILE_ON_NOTIFICATION" />
+
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
+
+ <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
+ <protected-broadcast android:name="com.android.bluetooth.map.USER_CONFIRM_TIMEOUT" />
+ <protected-broadcast android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_SENT" />
+ <protected-broadcast android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" />
+ <protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
+ <protected-broadcast android:name="android.content.syncmanager.SYNC_ALARM" />
+ <protected-broadcast android:name="android.media.INTERNAL_RINGER_MODE_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.STREAM_DEVICES_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.media.STREAM_MUTE_CHANGED_ACTION" />
+ <protected-broadcast android:name="android.net.sip.SIP_SERVICE_UP" />
+ <protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.os.action.CHARGING" />
+ <protected-broadcast android:name="android.os.action.DISCHARGING" />
+ <protected-broadcast android:name="android.search.action.SEARCHABLES_CHANGED" />
+ <protected-broadcast android:name="android.security.STORAGE_CHANGED" />
+ <protected-broadcast android:name="android.security.action.TRUST_STORE_CHANGED" />
+ <protected-broadcast android:name="android.security.action.KEYCHAIN_CHANGED" />
+ <protected-broadcast android:name="android.security.action.KEY_ACCESS_CHANGED" />
+ <protected-broadcast android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_REGISTERED" />
+ <protected-broadcast android:name="android.telecom.action.PHONE_ACCOUNT_UNREGISTERED" />
+ <protected-broadcast android:name="android.telecom.action.POST_CALL" />
+ <protected-broadcast android:name="android.telecom.action.SHOW_MISSED_CALLS_NOTIFICATION" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SECRET_CODE" />
+ <protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" />
+ <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" />
+
+ <protected-broadcast android:name="com.android.bluetooth.btservice.action.ALARM_WAKEUP" />
+ <protected-broadcast android:name="com.android.server.action.NETWORK_STATS_POLL" />
+ <protected-broadcast android:name="com.android.server.action.NETWORK_STATS_UPDATED" />
+ <protected-broadcast android:name="com.android.server.timedetector.NetworkTimeUpdateService.action.POLL" />
+ <protected-broadcast android:name="com.android.server.telecom.intent.action.CALLS_ADD_ENTRY" />
+ <protected-broadcast android:name="com.android.settings.location.MODE_CHANGING" />
+ <protected-broadcast android:name="com.android.settings.bluetooth.ACTION_DISMISS_PAIRING" />
+ <protected-broadcast android:name="com.android.settings.network.DELETE_SUBSCRIPTION" />
+ <protected-broadcast android:name="com.android.settings.network.SWITCH_TO_SUBSCRIPTION" />
+ <protected-broadcast android:name="com.android.settings.wifi.action.NETWORK_REQUEST" />
+
+ <protected-broadcast android:name="NotificationManagerService.TIMEOUT" />
+ <protected-broadcast android:name="NotificationHistoryDatabase.CLEANUP" />
+ <protected-broadcast android:name="ScheduleConditionProvider.EVALUATE" />
+ <protected-broadcast android:name="EventConditionProvider.EVALUATE" />
+ <protected-broadcast android:name="SnoozeHelper.EVALUATE" />
+ <protected-broadcast android:name="wifi_scan_available" />
+
+ <protected-broadcast android:name="action.cne.started" />
+ <protected-broadcast android:name="android.content.jobscheduler.JOB_DEADLINE_EXPIRED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_UNSOL_RESPONSE_OEM_HOOK_RAW" />
+ <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_SUPL" />
+ <protected-broadcast android:name="android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED" />
+ <protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
+ <protected-broadcast android:name="android.os.storage.action.DISK_SCANNED" />
+ <protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
+ <protected-broadcast android:name="com.android.server.action.RESET_TWILIGHT_AUTO" />
+ <protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
+ <protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
+ <protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
+ <protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
+ <protected-broadcast android:name="android.intent.action.MEDIA_RESOURCE_GRANTED" />
+ <protected-broadcast android:name="android.app.action.NETWORK_LOGS_AVAILABLE" />
+ <protected-broadcast android:name="android.app.action.SECURITY_LOGS_AVAILABLE" />
+ <protected-broadcast android:name="android.app.action.COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED" />
+
+ <protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED" />
+ <protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL" />
+ <protected-broadcast android:name="android.app.action.NOTIFICATION_POLICY_CHANGED" />
+ <protected-broadcast android:name="android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED" />
+ <protected-broadcast android:name="android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
+ <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED" />
+ <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED" />
+ <protected-broadcast android:name="android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED" />
+ <protected-broadcast android:name="android.app.action.APP_BLOCK_STATE_CHANGED" />
+
+ <protected-broadcast android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS" />
+ <protected-broadcast android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS" />
+
+ <protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
+
+ <protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
+ <protected-broadcast android:name="android.accounts.action.ACCOUNT_REMOVED" />
+ <protected-broadcast android:name="android.accounts.action.VISIBLE_ACCOUNTS_CHANGED" />
+
+ <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
+
+ <protected-broadcast android:name="android.net.sip.action.SIP_INCOMING_CALL" />
+ <protected-broadcast android:name="com.android.phone.SIP_ADD_PHONE" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_REMOVE_PROFILE" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_SERVICE_UP" />
+ <protected-broadcast android:name="android.net.sip.action.SIP_CALL_OPTION_CHANGED" />
+ <protected-broadcast android:name="android.net.sip.action.START_SIP" />
+
+ <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_CONNECTED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED" />
+
+ <protected-broadcast android:name="android.bluetooth.input.profile.action.HANDSHAKE" />
+ <protected-broadcast android:name="android.bluetooth.input.profile.action.REPORT" />
+
+ <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" />
+
+ <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" />
+ <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
+
+ <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
+ <protected-broadcast android:name="android.server.notification.action.ENABLE_NAS" />
+ <protected-broadcast android:name="android.server.notification.action.DISABLE_NAS" />
+ <protected-broadcast android:name="android.server.notification.action.LEARNMORE_NAS" />
+
+ <protected-broadcast android:name="com.android.internal.location.ALARM_WAKEUP" />
+ <protected-broadcast android:name="com.android.internal.location.ALARM_TIMEOUT" />
+ <protected-broadcast android:name="android.intent.action.GLOBAL_BUTTON" />
+
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
+ <protected-broadcast android:name="com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK" />
+
+ <protected-broadcast android:name="android.intent.action.PROFILE_ACCESSIBLE" />
+ <protected-broadcast android:name="android.intent.action.PROFILE_INACCESSIBLE" />
+
+ <protected-broadcast android:name="com.android.server.retaildemo.ACTION_RESET_DEMO" />
+
+ <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
+
+ <!-- Added in O -->
+ <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
+ <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
+ <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
+
+ <protected-broadcast android:name="android.content.pm.action.SESSION_COMMITTED" />
+ <protected-broadcast android:name="android.os.action.USER_RESTRICTIONS_CHANGED" />
+ <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT" />
+ <protected-broadcast android:name="android.media.tv.action.PREVIEW_PROGRAM_BROWSABLE_DISABLED" />
+ <protected-broadcast android:name="android.media.tv.action.WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
+ <protected-broadcast android:name="android.media.tv.action.CHANNEL_BROWSABLE_REQUESTED" />
+ <protected-broadcast android:name="com.android.server.inputmethod.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER" />
+
+ <!-- Made protected in P (was introduced in JB-MR2) -->
+ <protected-broadcast android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
+ <protected-broadcast android:name="android.telephony.euicc.action.OTA_STATUS_CHANGED" />
+
+ <!-- Added in P -->
+ <protected-broadcast android:name="android.app.action.PROFILE_OWNER_CHANGED" />
+ <protected-broadcast android:name="android.app.action.TRANSFER_OWNERSHIP_COMPLETE" />
+ <protected-broadcast android:name="android.app.action.AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE" />
+ <protected-broadcast android:name="android.app.action.STATSD_STARTED" />
+ <protected-broadcast android:name="com.android.server.biometrics.fingerprint.ACTION_LOCKOUT_RESET" />
+ <protected-broadcast android:name="com.android.server.biometrics.face.ACTION_LOCKOUT_RESET" />
+
+ <!-- For IdleController -->
+ <protected-broadcast android:name="android.intent.action.DOCK_IDLE" />
+ <protected-broadcast android:name="android.intent.action.DOCK_ACTIVE" />
+
+ <!-- Added in Q -->
+ <protected-broadcast android:name="android.content.pm.action.SESSION_UPDATED" />
+ <protected-broadcast android:name="android.settings.action.GRAYSCALE_CHANGED" />
+
+ <!-- For CarIdlenessTracker -->
+ <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_ON" />
+ <protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_OFF" />
+ <protected-broadcast android:name="com.android.server.jobscheduler.FORCE_IDLE" />
+ <protected-broadcast android:name="com.android.server.jobscheduler.UNFORCE_IDLE" />
+
+ <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL" />
+
+ <protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
+
+ <!-- Added in R -->
+ <protected-broadcast android:name="android.app.action.RESET_PROTECTION_POLICY_CHANGED" />
+
+ <!-- For tether entitlement recheck-->
+ <protected-broadcast
+ android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" />
+
+ <!-- Made protected in S (was added in R) -->
+ <protected-broadcast android:name="com.android.internal.intent.action.BUGREPORT_REQUESTED" />
+
+ <!-- Added in S -->
+ <protected-broadcast android:name="android.scheduling.action.REBOOT_READY" />
+ <protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" />
+ <protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" />
+
+ <!-- Moved from packages/services/Telephony in T -->
+ <protected-broadcast android:name="android.telecom.action.CURRENT_TTY_MODE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.SERVICE_STATE" />
+ <protected-broadcast android:name="android.intent.action.RADIO_TECHNOLOGY" />
+ <protected-broadcast android:name="android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.EMERGENCY_CALL_STATE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.SIG_STR" />
+ <protected-broadcast android:name="android.intent.action.ANY_DATA_STATE" />
+ <protected-broadcast android:name="android.intent.action.DATA_STALL_DETECTED" />
+ <protected-broadcast android:name="android.intent.action.SIM_STATE_CHANGED" />
+ <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
+ <protected-broadcast android:name="android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS" />
+ <protected-broadcast android:name="android.intent.action.ACTION_MDN_STATE_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SERVICE_PROVIDERS_UPDATED" />
+ <protected-broadcast android:name="android.provider.Telephony.SIM_FULL" />
+ <protected-broadcast android:name="com.android.internal.telephony.carrier_key_download_alarm" />
+ <protected-broadcast android:name="com.android.internal.telephony.data-restart-trysetup" />
+ <protected-broadcast android:name="com.android.internal.telephony.data-stall" />
+ <protected-broadcast android:name="com.android.internal.telephony.provisioning_apn_alarm" />
+ <protected-broadcast android:name="android.intent.action.DATA_SMS_RECEIVED" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_RECEIVED" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_DELIVER" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_REJECTED" />
+ <protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+ <protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_CB_RECEIVED" />
+ <protected-broadcast android:name="android.provider.action.SMS_EMERGENCY_CB_RECEIVED" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED" />
+ <protected-broadcast android:name="android.provider.Telephony.SECRET_CODE" />
+ <protected-broadcast android:name="com.android.internal.stk.command" />
+ <protected-broadcast android:name="com.android.internal.stk.session_end" />
+ <protected-broadcast android:name="com.android.internal.stk.icc_status_change" />
+ <protected-broadcast android:name="com.android.internal.stk.alpha_notify" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+ <protected-broadcast android:name="com.android.internal.telephony.PROVISION" />
+ <protected-broadcast android:name="com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED" />
+ <protected-broadcast android:name="com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED" />
+ <protected-broadcast android:name="com.android.intent.isim_refresh" />
+ <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_AVAILABLE" />
+ <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_UNAVAILABLE" />
+ <protected-broadcast android:name="com.android.ims.ACTION_RCS_SERVICE_DIED" />
+ <protected-broadcast android:name="com.android.ims.ACTION_PRESENCE_CHANGED" />
+ <protected-broadcast android:name="com.android.ims.ACTION_PUBLISH_STATUS_CHANGED" />
+ <protected-broadcast android:name="com.android.ims.IMS_SERVICE_UP" />
+ <protected-broadcast android:name="com.android.ims.IMS_SERVICE_DOWN" />
+ <protected-broadcast android:name="com.android.ims.IMS_INCOMING_CALL" />
+ <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
+ <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_DOWN" />
+ <protected-broadcast android:name="com.android.imsconnection.DISCONNECTED" />
+ <protected-broadcast android:name="com.android.intent.action.IMS_FEATURE_CHANGED" />
+ <protected-broadcast android:name="com.android.intent.action.IMS_CONFIG_CHANGED" />
+ <protected-broadcast android:name="android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR" />
+ <protected-broadcast android:name="com.android.phone.vvm.omtp.sms.REQUEST_SENT" />
+ <protected-broadcast android:name="com.android.phone.vvm.ACTION_VISUAL_VOICEMAIL_SERVICE_EVENT" />
+ <protected-broadcast android:name="com.android.internal.telephony.CARRIER_VVM_PACKAGE_INSTALLED" />
+ <protected-broadcast android:name="com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
+ <protected-broadcast android:name="com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD" />
+ <protected-broadcast android:name="com.android.internal.telephony.action.COUNTRY_OVERRIDE" />
+ <protected-broadcast android:name="com.android.internal.telephony.OPEN_DEFAULT_SMS_APP" />
+ <protected-broadcast android:name="com.android.internal.telephony.ACTION_TEST_OVERRIDE_CARRIER_ID" />
+ <protected-broadcast android:name="android.telephony.action.SIM_CARD_STATE_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SIM_APPLICATION_STATE_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SIM_SLOT_STATUS_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.TOGGLE_PROVISION" />
+ <protected-broadcast android:name="android.telephony.action.NETWORK_COUNTRY_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.MULTI_SIM_CONFIG_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_RESET" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_PCO_VALUE" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_REDIRECTED" />
+ <protected-broadcast android:name="android.telephony.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED" />
+ <protected-broadcast android:name="com.android.phone.settings.CARRIER_PROVISIONING" />
+ <protected-broadcast android:name="com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING" />
+ <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
+ <protected-broadcast android:name="android.intent.action.SUBSCRIPTION_INFO_RECORD_ADDED" />
+ <protected-broadcast android:name="android.intent.action.ACTION_MANAGED_ROAMING_IND" />
+ <protected-broadcast android:name="android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE" />
+
+ <!-- Added in T -->
+ <protected-broadcast android:name="android.app.action.LOST_MODE_LOCATION_UPDATE" />
+
+ <!-- ====================================================================== -->
+ <!-- RUNTIME PERMISSIONS -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Grouping for platform runtime permissions is not accessible to apps
+ @hide
+ @SystemApi
+ @TestApi
+ -->
+ <permission-group android:name="android.permission-group.UNDEFINED"
+ android:priority="100" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing user's contacts including personal profile -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for runtime permissions related to contacts and profiles on this
+ device. -->
+ <permission-group android:name="android.permission-group.CONTACTS"
+ android:icon="@drawable/perm_group_contacts"
+ android:label="@string/permgrouplab_contacts"
+ android:description="@string/permgroupdesc_contacts"
+ android:priority="100" />
+
+ <!-- Allows an application to read the user's contacts data.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.READ_CONTACTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readContacts"
+ android:description="@string/permdesc_readContacts"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write the user's contacts data.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.WRITE_CONTACTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_writeContacts"
+ android:description="@string/permdesc_writeContacts"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to set default account for new contacts.
+ <p> This permission is only granted to system applications fulfilling the Contacts app role.
+ <p>Protection level: internal|role
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS"
+ android:protectionLevel="internal|role" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing user's calendar -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for runtime permissions related to user's calendar. -->
+ <permission-group android:name="android.permission-group.CALENDAR"
+ android:icon="@drawable/perm_group_calendar"
+ android:label="@string/permgrouplab_calendar"
+ android:description="@string/permgroupdesc_calendar"
+ android:priority="200" />
+
+ <!-- Allows an application to read the user's calendar data.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.READ_CALENDAR"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readCalendar"
+ android:description="@string/permdesc_readCalendar"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write the user's calendar data.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.WRITE_CALENDAR"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_writeCalendar"
+ android:description="@string/permdesc_writeCalendar"
+ android:protectionLevel="dangerous" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing and modifying user's SMS messages -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Allows accessing the messages on ICC
+ @hide Used internally. -->
+ <permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC"
+ android:protectionLevel="signature" />
+
+ <!-- Used for runtime permissions related to user's SMS messages. -->
+ <permission-group android:name="android.permission-group.SMS"
+ android:icon="@drawable/perm_group_sms"
+ android:label="@string/permgrouplab_sms"
+ android:description="@string/permgroupdesc_sms"
+ android:priority="300" />
+
+ <!-- Allows an application to send SMS messages.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.SEND_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_sendSms"
+ android:description="@string/permdesc_sendSms"
+ android:permissionFlags="costsMoney|hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to receive SMS messages.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.RECEIVE_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_receiveSms"
+ android:description="@string/permdesc_receiveSms"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to read SMS messages.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.READ_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readSms"
+ android:description="@string/permdesc_readSms"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to receive WAP push messages.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.RECEIVE_WAP_PUSH"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_receiveWapPush"
+ android:description="@string/permdesc_receiveWapPush"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to monitor incoming MMS messages.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.RECEIVE_MMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_receiveMms"
+ android:description="@string/permdesc_receiveMms"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- @SystemApi @TestApi Allows an application to forward cell broadcast messages to the cell
+ broadcast module. This is required in order to bind to the cell broadcast service, and
+ ensures that only the system can forward messages to it.
+
+ <p>Protection level: signature
+
+ @hide -->
+ <permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE"
+ android:label="@string/permlab_bindCellBroadcastService"
+ android:description="@string/permdesc_bindCellBroadcastService"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
+ messages and to register a content observer to get notifications when
+ a cell broadcast has been received and added to the database. For
+ emergency alerts, the database is updated immediately after the
+ alert dialog and notification sound/vibration/speech are presented.
+ The "read" column is then updated after the user dismisses the alert.
+ This enables supplementary emergency assistance apps to start loading
+ additional emergency information (if Internet access is available)
+ when the alert is first received, and to delay presenting the info
+ to the user until after the initial alert dialog is dismissed.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+
+ @hide Pending API council approval -->
+ <permission android:name="android.permission.READ_CELL_BROADCASTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readCellBroadcasts"
+ android:description="@string/permdesc_readCellBroadcasts"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- @SystemApi @hide Allows an application to communicate over satellite.
+ Only granted if the application is a system app.-->
+ <permission android:name="android.permission.SATELLITE_COMMUNICATION"
+ android:protectionLevel="role|signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to bind with satellite service.
+ Only granted if the application is a system app.-->
+ <permission android:name="android.permission.BIND_SATELLITE_SERVICE"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- @hide Allows an application to bind with satellite gateway service.
+ Only granted if the application is a system app.-->
+ <permission android:name="android.permission.BIND_SATELLITE_GATEWAY_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing external storage -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for runtime permissions related to the shared external storage. -->
+ <permission-group android:name="android.permission-group.STORAGE"
+ android:icon="@drawable/perm_group_storage"
+ android:label="@string/permgrouplab_storage"
+ android:description="@string/permgroupdesc_storage"
+ android:priority="900" />
+
+ <!-- Allows an application to read from external storage.
+ <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
+ granted this permission.</p>
+ <p>This permission is enforced starting in API level 19. Before API level 19, this
+ permission is not enforced and all apps still have access to read from external storage.
+ You can test your app with the permission enforced by enabling <em>Protect USB
+ storage</em> under Developer options in the Settings app on a device running Android 4.1 or
+ higher.</p>
+ <p>Also starting in API level 19, this permission is <em>not</em> required to
+ read/write files in your application-specific directories returned by
+ {@link android.content.Context#getExternalFilesDir} and
+ {@link android.content.Context#getExternalCacheDir}.
+ <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 4 or higher.
+
+ <p> This is a soft restricted permission which cannot be held by an app it its
+ full form until the installer on record whitelists the permission.
+ Specifically, if the permission is allowlisted the holder app can access
+ external storage and the visual and aural media collections while if the
+ permission is not allowlisted the holder app can only access to the visual
+ and aural medial collections. Also the permission is immutably restricted
+ meaning that the allowlist state can be specified only at install time and
+ cannot change until the app is installed. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_sdcardRead"
+ android:description="@string/permdesc_sdcardRead"
+ android:permissionFlags="softRestricted|immutablyRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to read audio files from shared storage.
+ <p>Protection level: dangerous -->
+ <permission-group android:name="android.permission-group.READ_MEDIA_AURAL"
+ android:icon="@drawable/perm_group_read_media_aural"
+ android:label="@string/permgrouplab_readMediaAural"
+ android:description="@string/permgroupdesc_readMediaAural"
+ android:priority="950" />
+
+ <!-- Allows an application to read audio files from external storage.
+ <p>This permission is enforced starting in API level
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
+ must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.READ_MEDIA_AUDIO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readMediaAudio"
+ android:description="@string/permdesc_readMediaAudio"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to read image and video files from shared storage.
+ <p>Protection level: dangerous -->
+ <permission-group android:name="android.permission-group.READ_MEDIA_VISUAL"
+ android:icon="@drawable/perm_group_read_media_visual"
+ android:label="@string/permgrouplab_readMediaVisual"
+ android:description="@string/permgroupdesc_readMediaVisual"
+ android:priority="1000" />
+
+ <!-- Allows an application to read audio files from external storage.
+ <p>This permission is enforced starting in API level
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
+ must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.READ_MEDIA_VIDEO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readMediaVideo"
+ android:description="@string/permdesc_readMediaVideo"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to read image files from external storage.
+ <p>This permission is enforced starting in API level
+ {@link android.os.Build.VERSION_CODES#TIRAMISU}.
+ For apps with a <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> of {@link android.os.Build.VERSION_CODES#S} or lower, this permission
+ must not be used and the READ_EXTERNAL_STORAGE permission must be used instead.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.READ_MEDIA_IMAGES"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readMediaImage"
+ android:description="@string/permdesc_readMediaImage"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to read image or video files from external storage that a user has
+ selected via the permission prompt photo picker. Apps can check this permission to verify that
+ a user has decided to use the photo picker, instead of granting access to
+ {@link #READ_MEDIA_IMAGES or #READ_MEDIA_VIDEO}. It does not prevent apps from accessing the
+ standard photo picker manually.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readVisualUserSelect"
+ android:description="@string/permdesc_readVisualUserSelect"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write to external storage.
+ <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 4 or higher.
+ <p>Starting in API level 19, this permission is <em>not</em> required to
+ read/write files in your application-specific directories returned by
+ {@link android.content.Context#getExternalFilesDir} and
+ {@link android.content.Context#getExternalCacheDir}.
+ <p>If this permission is not allowlisted for an app that targets an API level before
+ {@link android.os.Build.VERSION_CODES#Q} this permission cannot be granted to apps.</p>
+ <p>Protection level: dangerous</p>
+ -->
+ <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_sdcardWrite"
+ android:description="@string/permdesc_sdcardWrite"
+ android:permissionFlags="softRestricted|immutablyRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to access any geographic locations persisted in the
+ user's shared collection.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.ACCESS_MEDIA_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_mediaLocation"
+ android:description="@string/permdesc_mediaLocation"
+ android:protectionLevel="dangerous" />
+
+ <!-- @hide @SystemApi @TestApi
+ Allows an application to modify OBB files visible to other apps. -->
+ <permission android:name="android.permission.WRITE_OBB"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application a broad access to external storage in scoped storage.
+ Intended to be used by few apps that need to manage files on behalf of the users.
+ <p>Protection level: signature|appop|preinstalled -->
+ <permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:protectionLevel="signature|appop|preinstalled" />
+
+ <!-- Allows an application to modify and delete media files on this device or any connected
+ storage device without user confirmation. Applications must already be granted the
+ {@link #READ_EXTERNAL_STORAGE} or {@link #MANAGE_EXTERNAL_STORAGE}} permissions for this
+ permission to take effect.
+ <p>Even if applications are granted this permission, if applications want to modify or
+ delete media files, they also must get the access by calling
+ {@link android.provider.MediaStore#createWriteRequest(ContentResolver, Collection)},
+ {@link android.provider.MediaStore#createDeleteRequest(ContentResolver, Collection)}, or
+ {@link android.provider.MediaStore#createTrashRequest(ContentResolver, Collection, boolean)}.
+ <p>This permission doesn't give read or write access directly. It only prevents the user
+ confirmation dialog for these requests.
+ <p>If applications are not granted {@link #ACCESS_MEDIA_LOCATION}, the system also pops up
+ the user confirmation dialog for the write request.
+ <p>Protection level: signature|appop|preinstalled -->
+ <permission android:name="android.permission.MANAGE_MEDIA"
+ android:protectionLevel="signature|appop|preinstalled" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the device location -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that allow accessing the device location. -->
+ <permission-group android:name="android.permission-group.LOCATION"
+ android:icon="@drawable/perm_group_location"
+ android:label="@string/permgrouplab_location"
+ android:description="@string/permgroupdesc_location"
+ android:priority="400" />
+
+ <!-- Allows an app to access precise location.
+ Alternatively, you might want {@link #ACCESS_COARSE_LOCATION}.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ACCESS_FINE_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_accessFineLocation"
+ android:description="@string/permdesc_accessFineLocation"
+ android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- Allows an app to access approximate location.
+ Alternatively, you might want {@link #ACCESS_FINE_LOCATION}.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_accessCoarseLocation"
+ android:description="@string/permdesc_accessCoarseLocation"
+ android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- Allows an app to access location in the background. If you're requesting this permission,
+ you must also request either {@link #ACCESS_COARSE_LOCATION} or
+ {@link #ACCESS_FINE_LOCATION}. Requesting this permission by itself doesn't give you
+ location access.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_accessBackgroundLocation"
+ android:permissionFlags="hardRestricted"
+ android:description="@string/permdesc_accessBackgroundLocation"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- Allows an application (emergency or advanced driver-assistance app) to bypass
+ location settings.
+ <p>Not for use by third-party applications.
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.LOCATION_BYPASS"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the call log -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated telephony features. -->
+ <permission-group android:name="android.permission-group.CALL_LOG"
+ android:icon="@drawable/perm_group_call_log"
+ android:label="@string/permgrouplab_calllog"
+ android:description="@string/permgroupdesc_calllog"
+ android:priority="450" />
+
+ <!-- Allows an application to access the IMS call service: making and
+ modifying a call
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_IMS_CALL_SERVICE"
+ android:label="@string/permlab_accessImsCallService"
+ android:description="@string/permdesc_accessImsCallService"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to perform IMS Single Registration related actions.
+ Only granted if the application is a system app AND is in the Default SMS Role.
+ The permission is revoked when the app is taken out of the Default SMS Role.
+ <p>Protection level: internal|role
+ -->
+ <permission android:name="android.permission.PERFORM_IMS_SINGLE_REGISTRATION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to read the user's call log.
+ <p class="note"><strong>Note:</strong> If your app uses the
+ {@link #READ_CONTACTS} permission and <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 16 or higher.</p>
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.READ_CALL_LOG"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readCallLog"
+ android:description="@string/permdesc_readCallLog"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to write (but not read) the user's
+ call log data.
+ <p class="note"><strong>Note:</strong> If your app uses the
+ {@link #WRITE_CONTACTS} permission and <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 15 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 16 or higher.</p>
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.WRITE_CALL_LOG"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_writeCallLog"
+ android:description="@string/permdesc_writeCallLog"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to see the number being dialed during an outgoing
+ call with the option to redirect the call to a different number or
+ abort the call altogether.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record whitelists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+
+ @deprecated Applications should use {@link android.telecom.CallRedirectionService} instead
+ of the {@link android.content.Intent#ACTION_NEW_OUTGOING_CALL} broadcast.
+ -->
+ <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_processOutgoingCalls"
+ android:description="@string/permdesc_processOutgoingCalls"
+ android:permissionFlags="hardRestricted"
+ android:protectionLevel="dangerous" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the device telephony -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated telephony features. -->
+ <permission-group android:name="android.permission-group.PHONE"
+ android:icon="@drawable/perm_group_phone_calls"
+ android:label="@string/permgrouplab_phone"
+ android:description="@string/permgroupdesc_phone"
+ android:priority="500" />
+
+ <!-- Allows read only access to phone state, including the current cellular network information,
+ the status of any ongoing calls, and a list of any {@link android.telecom.PhoneAccount}s
+ registered on the device.
+ <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 4 or higher.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.READ_PHONE_STATE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readPhoneState"
+ android:description="@string/permdesc_readPhoneState"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
+ granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
+ <p>Protection level: dangerous-->
+ <permission android:name="android.permission.READ_PHONE_NUMBERS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readPhoneNumbers"
+ android:description="@string/permdesc_readPhoneNumbers"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- Allows an application to initiate a phone call without going through
+ the Dialer user interface for the user to confirm the call.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.CALL_PHONE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:permissionFlags="costsMoney"
+ android:label="@string/permlab_callPhone"
+ android:description="@string/permdesc_callPhone"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to add voicemails into the system.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_addVoicemail"
+ android:description="@string/permdesc_addVoicemail"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to use SIP service.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.USE_SIP"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_use_sip"
+ android:label="@string/permlab_use_sip"
+ android:protectionLevel="dangerous"/>
+
+ <!-- Allows the app to answer an incoming phone call.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ANSWER_PHONE_CALLS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_answerPhoneCalls"
+ android:description="@string/permdesc_answerPhoneCalls"
+ android:protectionLevel="dangerous|runtime" />
+
+ <!-- Allows a calling application which manages its own calls through the self-managed
+ {@link android.telecom.ConnectionService} APIs. See
+ {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED} for more information on the
+ self-managed ConnectionService APIs.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.MANAGE_OWN_CALLS"
+ android:label="@string/permlab_manageOwnCalls"
+ android:description="@string/permdesc_manageOwnCalls"
+ android:protectionLevel="normal" />
+
+ <!--Allows an app which implements the
+ {@link android.telecom.InCallService InCallService} API to be eligible to be enabled as a
+ calling companion app. This means that the Telecom framework will bind to the app's
+ InCallService implementation when there are calls active. The app can use the InCallService
+ API to view information about calls on the system and control these calls.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CALL_COMPANION_APP"
+ android:label="@string/permlab_callCompanionApp"
+ android:description="@string/permdesc_callCompanionApp"
+ android:protectionLevel="normal" />
+
+ <!-- Exempt this uid from restrictions to background audio recoding
+ <p>Protection level: signature|privileged
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS"
+ android:label="@string/permlab_exemptFromAudioRecordRestrictions"
+ android:description="@string/permdesc_exemptFromAudioRecordRestrictions"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows a calling app to continue a call which was started in another app. An example is a
+ video calling app that wants to continue a voice call on the user's mobile network.<p>
+ When the handover of a call from one app to another takes place, there are two devices
+ which are involved in the handover; the initiating and receiving devices. The initiating
+ device is where the request to handover the call was started, and the receiving device is
+ where the handover request is confirmed by the other party.<p>
+ This permission protects access to the
+ {@link android.telecom.TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} which
+ the receiving side of the handover uses to accept a handover.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ACCEPT_HANDOVER"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android.label="@string/permlab_acceptHandover"
+ android:description="@string/permdesc_acceptHandovers"
+ android:protectionLevel="dangerous" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the device microphone -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with accessing
+ microphone audio from the device. Note that phone calls also capture audio
+ but are in a separate (more visible) permission group. -->
+ <permission-group android:name="android.permission-group.MICROPHONE"
+ android:icon="@drawable/perm_group_microphone"
+ android:label="@string/permgrouplab_microphone"
+ android:description="@string/permgroupdesc_microphone"
+ android:priority="600" />
+
+ <!-- Allows an application to record audio.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.RECORD_AUDIO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_recordAudio"
+ android:description="@string/permdesc_recordAudio"
+ android:backgroundPermission="android.permission.RECORD_BACKGROUND_AUDIO"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- @SystemApi @TestApi Allows an application to record audio while in the background.
+ This permission is not intended to be held by apps.
+ <p>Protection level: internal
+ @hide -->
+ <permission android:name="android.permission.RECORD_BACKGROUND_AUDIO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_recordBackgroundAudio"
+ android:description="@string/permdesc_recordBackgroundAudio"
+ android:protectionLevel="internal|role" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for activity recognition -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with activity recognition. -->
+ <permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION"
+ android:icon="@drawable/perm_group_activity_recognition"
+ android:label="@string/permgrouplab_activityRecognition"
+ android:description="@string/permgroupdesc_activityRecognition"
+ android:priority="1000" />
+
+ <!-- Allows an application to recognize physical activity.
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.ACTIVITY_RECOGNITION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_activityRecognition"
+ android:description="@string/permdesc_activityRecognition"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the vendor UCE Service -->
+ <!-- ====================================================================== -->
+
+ <!-- @hide Allows an application to Access UCE-Presence.
+ <p>Protection level: signature|privileged
+ @deprecated Framework should no longer use this permission to access the vendor UCE service
+ using AIDL, it is instead implemented by RcsCapabilityExchangeImplBase
+ -->
+ <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- @hide Allows an application to Access UCE-OPTIONS.
+ <p>Protection level: signature|privileged
+ @deprecated Framework should no longer use this permission to access the vendor UCE service
+ using AIDL, it is instead implemented by RcsCapabilityExchangeImplBase
+ -->
+ <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
+ android:permissionGroup="android.permission-group.PHONE"
+ android:protectionLevel="signature|privileged"/>
+
+
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the device camera -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with accessing
+ camera or capturing images/video from the device. -->
+ <permission-group android:name="android.permission-group.CAMERA"
+ android:icon="@drawable/perm_group_camera"
+ android:label="@string/permgrouplab_camera"
+ android:description="@string/permgroupdesc_camera"
+ android:priority="700" />
+
+ <!-- Required to be able to access the camera device.
+ <p>This will automatically enforce the
+ <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">
+ uses-feature</a> manifest element for <em>all</em> camera features.
+ If you do not require all camera features or can properly operate if a camera
+ is not available, then you must modify your manifest as appropriate in order to
+ install on devices that don't support all camera features.</p>
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.CAMERA"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_camera"
+ android:description="@string/permdesc_camera"
+ android:backgroundPermission="android.permission.BACKGROUND_CAMERA"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- Required to be able to discover and connect to nearby Bluetooth devices.
+ <p>Protection level: dangerous -->
+ <permission-group android:name="android.permission-group.NEARBY_DEVICES"
+ android:icon="@drawable/perm_group_nearby_devices"
+ android:label="@string/permgrouplab_nearby_devices"
+ android:description="@string/permgroupdesc_nearby_devices"
+ android:priority="750" />
+
+ <!-- @SystemApi @TestApi Required to be able to access the camera device in the background.
+ This permission is not intended to be held by apps.
+ <p>Protection level: internal
+ @hide -->
+ <permission android:name="android.permission.BACKGROUND_CAMERA"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_backgroundCamera"
+ android:description="@string/permdesc_backgroundCamera"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Required in addition to android.permission.CAMERA to be able to access
+ system only camera devices.
+ <p>Protection level: system|signature|role
+ @hide -->
+ <permission android:name="android.permission.SYSTEM_CAMERA"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_systemCamera"
+ android:description="@string/permdesc_systemCamera"
+ android:protectionLevel="system|signature|role" />
+
+ <!-- @SystemApi Allows receiving the camera service notifications when a camera is opened
+ (by a certain application package) or closed.
+ @hide -->
+ <permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_cameraOpenCloseListener"
+ android:description="@string/permdesc_cameraOpenCloseListener"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows camera access by Headless System User 0 when device is running in
+ HSUM Mode.
+ @hide -->
+ <permission android:name="android.permission.CAMERA_HEADLESS_SYSTEM_USER"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_cameraHeadlessSystemUser"
+ android:description="@string/permdesc_cameraHeadlessSystemUser"
+ android:protectionLevel="signature" />
+
+ <!-- ====================================================================== -->
+ <!-- Permissions for accessing the device sensors -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with accessing
+ body or environmental sensors. -->
+ <permission-group android:name="android.permission-group.SENSORS"
+ android:icon="@drawable/perm_group_sensors"
+ android:label="@string/permgrouplab_sensors"
+ android:description="@string/permgroupdesc_sensors"
+ android:priority="800" />
+
+ <!-- Allows an app to access sensor data with a sampling rate greater than 200 Hz.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_highSamplingRateSensors"
+ android:description="@string/permdesc_highSamplingRateSensors"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to access data from sensors that the user uses to
+ measure what is happening inside their body, such as heart rate.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.BODY_SENSORS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_bodySensors"
+ android:description="@string/permdesc_bodySensors"
+ android:backgroundPermission="android.permission.BODY_SENSORS_BACKGROUND"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows an application to access data from sensors that the user uses to measure what is
+ happening inside their body, such as heart rate. If you're requesting this permission, you
+ must also request {@link #BODY_SENSORS}. Requesting this permission by itself doesn't give
+ you Body sensors access.
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record allowlists the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+ -->
+ <permission android:name="android.permission.BODY_SENSORS_BACKGROUND"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_bodySensors_background"
+ android:description="@string/permdesc_bodySensors_background"
+ android:protectionLevel="dangerous"
+ android:permissionFlags="hardRestricted" />
+
+ <!-- Allows an app to use fingerprint hardware.
+ <p>Protection level: normal
+ @deprecated Applications should request {@link
+ android.Manifest.permission#USE_BIOMETRIC} instead
+ -->
+ <permission android:name="android.permission.USE_FINGERPRINT"
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_useFingerprint"
+ android:description="@string/permdesc_useFingerprint"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an app to use device supported biometric modalities.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.USE_BIOMETRIC"
+ android:permissionGroup="android.permission-group.SENSORS"
+ android:label="@string/permlab_useBiometric"
+ android:description="@string/permdesc_useBiometric"
+ android:protectionLevel="normal" />
+
+ <!-- ======================================================================= -->
+ <!-- Permissions for posting notifications -->
+ <!-- ====================================================================== -->
+ <eat-comment />
+
+ <!-- Used for permissions that are associated with posting notifications
+ -->
+ <permission-group android:name="android.permission-group.NOTIFICATIONS"
+ android:icon="@drawable/ic_notifications_alerted"
+ android:label="@string/permgrouplab_notifications"
+ android:description="@string/permgroupdesc_notifications"
+ android:priority="850" />
+
+ <!-- Allows an app to post notifications
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.POST_NOTIFICATIONS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_postNotification"
+ android:description="@string/permdesc_postNotification"
+ android:protectionLevel="dangerous|instant" />
+
+ <!-- ====================================================================== -->
+ <!-- REMOVED PERMISSIONS -->
+ <!-- ====================================================================== -->
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.READ_PROFILE"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.WRITE_PROFILE"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.READ_SOCIAL_STREAM"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.WRITE_SOCIAL_STREAM"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.READ_USER_DICTIONARY"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.WRITE_USER_DICTIONARY"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.WRITE_SMS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.MANAGE_ACCOUNTS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.USE_CREDENTIALS"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.SUBSCRIBED_FEEDS_READ"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- @hide We need to keep this around for backwards compatibility -->
+ <permission android:name="android.permission.FLASHLIGHT"
+ android:protectionLevel="normal"
+ android:permissionFlags="removed"/>
+
+ <!-- ====================================================================== -->
+ <!-- INSTALL PERMISSIONS -->
+ <!-- ====================================================================== -->
+
+ <!-- ================================== -->
+ <!-- Permissions for accessing messages -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows an application (Phone) to send a request to other applications
+ to handle the respond-via-message action during incoming calls.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to filter carrier specific sms.
+ @hide -->
+ <permission android:name="android.permission.CARRIER_FILTER_SMS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to receive emergency cell broadcast messages,
+ to record or display them to the user.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_EMERGENCY_BROADCAST"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to monitor incoming Bluetooth MAP messages, to record
+ or perform processing on them. -->
+ <!-- @hide -->
+ <permission android:name="android.permission.RECEIVE_BLUETOOTH_MAP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to execute contacts directory search.
+ This should only be used by ContactsProvider.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to modify the cell broadcasts configuration
+ (i.e. enable or disable channels).
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MODIFY_CELL_BROADCASTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- =============================================================== -->
+ <!-- Permissions for setting the device alarm -->
+ <!-- =============================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to broadcast an Intent to set an alarm for the user.
+ <p>Protection level: normal
+ -->
+ <permission android:name="com.android.alarm.permission.SET_ALARM"
+ android:label="@string/permlab_setAlarm"
+ android:description="@string/permdesc_setAlarm"
+ android:protectionLevel="normal" />
+
+ <!-- =============================================================== -->
+ <!-- Permissions for accessing the user voicemail -->
+ <!-- =============================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to modify and remove existing voicemails in the system.
+ <p>Protection level: signature|privileged|role
+ -->
+ <permission android:name="com.android.voicemail.permission.WRITE_VOICEMAIL"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an application to read voicemails in the system.
+ <p>Protection level: signature|privileged|role
+ -->
+ <permission android:name="com.android.voicemail.permission.READ_VOICEMAIL"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- ======================================= -->
+ <!-- Permissions for accessing location info -->
+ <!-- ======================================= -->
+ <eat-comment />
+
+ <!-- Allows an application to access extra location provider commands.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"
+ android:label="@string/permlab_accessLocationExtraCommands"
+ android:description="@string/permdesc_accessLocationExtraCommands"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to install a location provider into the Location Manager.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.INSTALL_LOCATION_PROVIDER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to provide location-based time zone suggestions to
+ the system server. This is needed because the system server discovers time zone providers
+ by exposed intent actions and metadata, without it any app could potentially register
+ itself as time zone provider. The system server checks for this permission.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to bind to a android.service.TimeZoneProviderService
+ for the purpose of detecting the device's time zone. This prevents arbitrary clients
+ connecting to the time zone provider service. The system server checks that the provider's
+ intent service explicitly sets this permission via the android:permission attribute of the
+ service.
+ This is only expected to be possessed by the system server outside of tests.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.BIND_TIME_ZONE_PROVIDER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows HDMI-CEC service to access device and configuration files.
+ This should only be used by HDMI-CEC service.
+ -->
+ <permission android:name="android.permission.HDMI_CEC"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- Allows an application to use location features in hardware,
+ such as the geofencing api.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.LOCATION_HARDWARE"
+ android:protectionLevel="signature|privileged|role" />
+ <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
+
+ <!-- @SystemApi Allows an application to use the Context Hub.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_CONTEXT_HUB"
+ android:protectionLevel="signature|privileged" />
+ <uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB"/>
+
+ <!-- @SystemApi Allows an application to create mock location providers for testing.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows automotive applications to control location
+ suspend state for power management use cases.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.CONTROL_AUTOMOTIVE_GNSS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- ======================================= -->
+ <!-- Permissions for accessing networks -->
+ <!-- ======================================= -->
+ <eat-comment />
+
+ <!-- Allows applications to open network sockets.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.INTERNET"
+ android:description="@string/permdesc_createNetworkSockets"
+ android:label="@string/permlab_createNetworkSockets"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows applications to access information about networks.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.ACCESS_NETWORK_STATE"
+ android:description="@string/permdesc_accessNetworkState"
+ android:label="@string/permlab_accessNetworkState"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows applications to access information about Wi-Fi networks.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.ACCESS_WIFI_STATE"
+ android:description="@string/permdesc_accessWifiState"
+ android:label="@string/permlab_accessWifiState"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to change Wi-Fi connectivity state.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CHANGE_WIFI_STATE"
+ android:description="@string/permdesc_changeWifiState"
+ android:label="@string/permlab_changeWifiState"
+ android:protectionLevel="normal" />
+
+ <!-- This permission is used to let OEMs grant their trusted app access to a subset of
+ privileged wifi APIs to improve wifi performance. Allows applications to manage
+ Wi-Fi network selection related features such as enable or disable global auto-join,
+ modify connectivity scan intervals, and approve Wi-Fi Direct connections.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_WIFI_NETWORK_SELECTION"
+ android:protectionLevel="signature|privileged|knownSigner"
+ android:knownCerts="@array/wifi_known_signers" />
+
+ <!-- Allows applications to get notified when a Wi-Fi interface request cannot
+ be satisfied without tearing down one or more other interfaces, and provide a decision
+ whether to approve the request or reject it.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_WIFI_INTERFACES"
+ android:protectionLevel="signature|privileged|knownSigner"
+ android:knownCerts="@array/wifi_known_signers" />
+
+ <!-- @SystemApi @hide Allows apps to create and manage IPsec tunnels.
+ <p>Only granted to applications that are currently bound by the
+ system for creating and managing IPsec-based interfaces.
+ -->
+ <permission android:name="android.permission.MANAGE_IPSEC_TUNNELS"
+ android:protectionLevel="signature|appop" />
+
+ <!-- @SystemApi @hide Allows apps to create and manage Test Networks.
+ <p>Granted only to shell. CTS tests will use
+ UiAutomation.AdoptShellPermissionIdentity() to gain access.
+ -->
+ <permission android:name="android.permission.MANAGE_TEST_NETWORKS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows direct access to the <RemoteAuth>Service interfaces.
+ @hide @TestApi @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) -->
+ <permission android:name="android.permission.MANAGE_REMOTE_AUTH"
+ android:protectionLevel="signature" />
+
+ <!-- Allows direct access to the <RemoteAuth>Service authentication methods.
+ @hide @TestApi @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) -->
+ <permission android:name="android.permission.USE_REMOTE_AUTH"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows applications to change tether state and run
+ tether carrier provisioning.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.TETHER_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allow system apps to receive broadcast
+ when a wifi network credential is changed.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to modify any wifi configuration, even if created
+ by another application. Once reconfigured the original creator cannot make any further
+ modifications.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
+ android:protectionLevel="signature|privileged|knownSigner"
+ android:knownCerts="@array/wifi_known_signers" />
+
+ <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+ <permission android:name="android.permission.SCORE_NETWORKS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows applications to request network
+ recommendations and scores from the NetworkScoreService.
+ @SystemApi
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.REQUEST_NETWORK_SCORES"
+ android:protectionLevel="signature|setup" />
+
+ <!-- Allows applications to restart the Wi-Fi subsystem.
+ @SystemApi
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.RESTART_WIFI_SUBSYSTEM"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows applications to toggle airplane mode.
+ <p>Not for use by third-party or privileged applications.
+ -->
+ <permission android:name="android.permission.NETWORK_AIRPLANE_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows network stack services (Connectivity and Wifi) to coordinate
+ <p>Not for use by third-party or privileged applications.
+ @SystemApi @TestApi
+ @hide This should only be used by Connectivity and Wifi Services.
+ -->
+ <permission android:name="android.permission.NETWORK_STACK"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to observe network policy changes. -->
+ <permission android:name="android.permission.OBSERVE_NETWORK_POLICY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows applications to register network factory or agent -->
+ <permission android:name="android.permission.NETWORK_FACTORY"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows applications to access network stats provider -->
+ <permission android:name="android.permission.NETWORK_STATS_PROVIDER"
+ android:protectionLevel="signature" />
+
+ <!-- Allows Settings and SystemUI to call methods in Networking services
+ <p>Not for use by third-party or privileged applications.
+ @SystemApi @TestApi
+ @hide This should only be used by Settings and SystemUI.
+ -->
+ <permission android:name="android.permission.NETWORK_SETTINGS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and
+ location permissions.
+ <p>Not for use by third-party or privileged applications.
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"
+ android:protectionLevel="signature|companion" />
+
+ <!-- Allows SetupWizard to call methods in Networking services
+ <p>Not for use by any other third-party or privileged applications.
+ @SystemApi
+ @hide This should only be used by SetupWizard.
+ -->
+ <permission android:name="android.permission.NETWORK_SETUP_WIZARD"
+ android:protectionLevel="signature|setup" />
+
+ <!-- Allows Managed Provisioning to call methods in Networking services
+ <p>Not for use by any other third-party or privileged applications.
+ @SystemApi
+ @hide This should only be used by ManagedProvisioning app.
+ -->
+ <permission android:name="android.permission.NETWORK_MANAGED_PROVISIONING"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows Carrier Provisioning to call methods in Networking services
+ <p>Not for use by any other third-party or privileged applications.
+ @SystemApi
+ @hide This should only be used by CarrierProvisioning.
+ -->
+ <permission android:name="android.permission.NETWORK_CARRIER_PROVISIONING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- #SystemApi @hide Allows applications to access information about LoWPAN interfaces.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.ACCESS_LOWPAN_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- #SystemApi @hide Allows applications to change LoWPAN connectivity state.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_LOWPAN_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- #SystemApi @hide Allows applications to read LoWPAN credential.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_LOWPAN_CREDENTIAL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- #SystemApi @hide Allows a service to register or unregister
+ new LoWPAN interfaces.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_LOWPAN_INTERFACES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- #SystemApi @hide Allows an app to bypass Private DNS.
+ <p>Not for use by third-party applications.
+ TODO: publish as system API in next API release. -->
+ <permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows device mobility state to be set so that Wifi scan interval can
+ be increased when the device is stationary in order to save power.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WIFI_SET_DEVICE_MOBILITY_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows privileged system APK to update Wifi usability stats and score.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WIFI_UPDATE_USABILITY_STATS_SCORE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows applications to update Wifi/Cellular coex channels to avoid.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows applications to access Wifi/Cellular coex channels being avoided.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows system APK to manage country code.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_WIFI_COUNTRY_CODE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to manage an automotive device's application network
+ preference as it relates to OEM_PAID and OEM_PRIVATE capable networks.
+ <p>Not for use by third-party or privileged applications. -->
+ <permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to manage ethernet networks.
+ <p>Not for use by third-party or privileged applications. -->
+ <permission android:name="android.permission.MANAGE_ETHERNET_NETWORKS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows system apps to call methods to register itself as a mDNS offload engine.
+ <p>Not for use by third-party or privileged applications.
+ @SystemApi
+ @hide This should only be used by system apps.
+ -->
+ <permission android:name="android.permission.REGISTER_NSD_OFFLOAD_ENGINE"
+ android:protectionLevel="signature" />
+
+ <!-- ======================================= -->
+ <!-- Permissions for short range, peripheral networks -->
+ <!-- ======================================= -->
+ <eat-comment />
+
+ <!-- Allows applications to connect to paired bluetooth devices.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.BLUETOOTH"
+ android:description="@string/permdesc_bluetooth"
+ android:label="@string/permlab_bluetooth"
+ android:protectionLevel="normal" />
+
+ <!-- Required to be able to discover and pair nearby Bluetooth devices.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.BLUETOOTH_SCAN"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_bluetooth_scan"
+ android:label="@string/permlab_bluetooth_scan"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to connect to paired Bluetooth devices.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.BLUETOOTH_CONNECT"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_bluetooth_connect"
+ android:label="@string/permlab_bluetooth_connect"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to advertise to nearby Bluetooth devices.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.BLUETOOTH_ADVERTISE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_bluetooth_advertise"
+ android:label="@string/permlab_bluetooth_advertise"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to range to devices using ultra-wideband.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.UWB_RANGING"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_uwb_ranging"
+ android:label="@string/permlab_uwb_ranging"
+ android:protectionLevel="dangerous" />
+
+ <!-- Required to be able to advertise and connect to nearby devices via Wi-Fi.
+ <p>Protection level: dangerous -->
+ <permission android:name="android.permission.NEARBY_WIFI_DEVICES"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:description="@string/permdesc_nearby_wifi_devices"
+ android:label="@string/permlab_nearby_wifi_devices"
+ android:protectionLevel="dangerous" />
+
+ <!-- @SystemApi @TestApi Allows an application to suspend other apps, which will prevent the
+ user from using them until they are unsuspended.
+ @hide
+ -->
+ <permission android:name="android.permission.SUSPEND_APPS"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows applications to discover and pair bluetooth devices.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.BLUETOOTH_ADMIN"
+ android:description="@string/permdesc_bluetoothAdmin"
+ android:label="@string/permlab_bluetoothAdmin"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to pair bluetooth devices without user interaction, and to
+ allow or disallow phonebook access or message access.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- SystemApi Control access to email providers exclusively for Bluetooth
+ @hide
+ -->
+ <permission android:name="android.permission.BLUETOOTH_MAP"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows bluetooth stack to access files
+ @hide This should only be used by Bluetooth apk.
+ -->
+ <permission android:name="android.permission.BLUETOOTH_STACK"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows uhid write access for creating virtual input devices
+ @hide
+ -->
+ <permission android:name="android.permission.VIRTUAL_INPUT_DEVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows applications to perform I/O operations over NFC.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.NFC"
+ android:description="@string/permdesc_nfc"
+ android:label="@string/permlab_nfc"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to receive NFC transaction events.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to receive NFC preferred payment service information.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO"
+ android:description="@string/permdesc_preferredPaymentInfo"
+ android:label="@string/permlab_preferredPaymentInfo"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi Allows access to set NFC controller always on states.
+ <p>Protection level: signature|privileged
+ @hide -->
+ <permission android:name="android.permission.NFC_SET_CONTROLLER_ALWAYS_ON"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an internal user to use privileged SecureElement APIs.
+ Applications holding this permission can access OMAPI reset system API
+ and bypass OMAPI AccessControlEnforcer.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
+ uses have been replaced by a more appropriate permission. Most uses have been replaced with
+ a NETWORK_STACK or NETWORK_SETTINGS check. Please look up the documentation of the
+ individual functions to figure out what permission now protects the individual function.
+ @SystemApi Allows an internal user to use privileged ConnectivityManager APIs.
+ @hide -->
+ <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an internal user to use restricted Networks.
+ @hide -->
+ <permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
+ android:protectionLevel="signature|privileged" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+
+ <!-- @SystemApi Allows an internal user to set signal strength in NetworkRequest. This kind of
+ request will wake up device when signal strength meets the given value.
+ @hide -->
+ <permission android:name="android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows a system application to access hardware packet offload capabilities.
+ @hide -->
+ <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_DATA_ACTIVITY_CHANGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows access to the loop radio (Android@Home mesh network) device.
+ @hide -->
+ <permission android:name="android.permission.LOOP_RADIO"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows sending and receiving handover transfer status from Wifi and Bluetooth
+ @hide -->
+ <permission android:name="android.permission.NFC_HANDOVER_STATUS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows internal management of Bluetooth state when on wireless consent mode.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows the device to be reset, clearing all data and enables Test Harness Mode. -->
+ <permission android:name="android.permission.ENABLE_TEST_HARNESS_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows access to ultra wideband device.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.UWB_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- ================================== -->
+ <!-- Permissions for accessing accounts -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows access to the list of accounts in the Accounts Service.
+
+ <p class="note"><strong>Note:</strong> Beginning with Android 6.0 (API level
+ 23), if an app shares the signature of the authenticator that manages an
+ account, it does not need <code>"GET_ACCOUNTS"</code> permission to read
+ information about that account. On Android 5.1 and lower, all apps need
+ <code>"GET_ACCOUNTS"</code> permission to read information about any
+ account.</p>
+
+ <p>Protection level: dangerous
+ -->
+ <permission android:name="android.permission.GET_ACCOUNTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:protectionLevel="dangerous"
+ android:description="@string/permdesc_getAccounts"
+ android:label="@string/permlab_getAccounts" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
+
+ <!-- Allows applications to call into AccountAuthenticators.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.ACCOUNT_MANAGER"
+ android:protectionLevel="signature" />
+
+ <!-- ================================== -->
+ <!-- Permissions for accessing hardware that may effect battery life-->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows applications to enter Wi-Fi Multicast mode.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
+ android:description="@string/permdesc_changeWifiMulticastState"
+ android:label="@string/permlab_changeWifiMulticastState"
+ android:protectionLevel="normal" />
+
+ <!-- Allows access to the vibrator.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.VIBRATE"
+ android:label="@string/permlab_vibrate"
+ android:description="@string/permdesc_vibrate"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows access to the vibrator always-on settings.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.VIBRATE_ALWAYS_ON"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows access to the vibrator state.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_VIBRATOR_STATE"
+ android:label="@string/permdesc_vibrator_state"
+ android:description="@string/permdesc_vibrator_state"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
+ from dimming.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.WAKE_LOCK"
+ android:label="@string/permlab_wakeLock"
+ android:description="@string/permdesc_wakeLock"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows using the device's IR transmitter, if available.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.TRANSMIT_IR"
+ android:label="@string/permlab_transmitIr"
+ android:description="@string/permdesc_transmitIr"
+ android:protectionLevel="normal" />
+
+ <!-- ==================================================== -->
+ <!-- Permissions related to changing audio settings -->
+ <!-- ==================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to modify global audio settings.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
+ android:label="@string/permlab_modifyAudioSettings"
+ android:description="@string/permdesc_modifyAudioSettings"
+ android:protectionLevel="normal" />
+
+ <!-- ==================================================== -->
+ <!-- Permissions related to screen capture -->
+ <!-- ==================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to capture screen content to perform a screenshot using the intent
+ action {@link android.content.Intent#ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE}.
+ <p>Protection level: internal|role
+ <p>Intended for use by ROLE_NOTES only.
+ -->
+ <permission android:name="android.permission.LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to be notified whenever a screen capture is attempted.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.DETECT_SCREEN_CAPTURE"
+ android:label="@string/permlab_detectScreenCapture"
+ android:description="@string/permdesc_detectScreenCapture"
+ android:protectionLevel="normal" />
+
+ <!-- ======================================== -->
+ <!-- Permissions for factory reset protection -->
+ <!-- ======================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi Allows an application to set a factory reset protection (FRP) policy.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_FACTORY_RESET_PROTECTION"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- ======================================== -->
+ <!-- Permissions for lost mode -->
+ <!-- ======================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi Allows an application to trigger lost mode on an organization-owned device.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.TRIGGER_LOST_MODE"
+ android:protectionLevel="signature|role"/>
+
+ <!-- ================================== -->
+ <!-- Permissions for accessing hardware -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi Allows an application to manage preferences and permissions for USB devices
+ @hide -->
+ <permission android:name="android.permission.MANAGE_USB"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to manage Android Debug Bridge settings.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_DEBUGGING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to access the MTP USB kernel driver.
+ For use only by the device side MTP implementation.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_MTP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows access to hardware peripherals. Intended only for hardware testing.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.HARDWARE_TEST"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to manage DynamicSystem image -->
+ <permission android:name="android.permission.MANAGE_DYNAMIC_SYSTEM"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to install a DynamicSystem image and get status updates.
+ @hide -->
+ <permission android:name="android.permission.INSTALL_DYNAMIC_SYSTEM"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows access to Broadcast Radio
+ @hide This is not a third-party API (intended for system apps).-->
+ <permission android:name="android.permission.ACCESS_BROADCAST_RADIO"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @deprecated @SystemApi Allows access to FM
+ @hide This is not a third-party API (intended for system apps).-->
+ <permission android:name="android.permission.ACCESS_FM_RADIO"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows access to configure network interfaces, configure/use IPSec, etc.
+ @hide -->
+ <permission android:name="android.permission.NET_ADMIN"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows registration for remote audio playback. @hide -->
+ <permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
+ android:protectionLevel="signature" />
+
+ <!-- Allows TvInputService to access underlying TV input hardware such as
+ built-in tuners and HDMI-in's.
+ <p>This should only be used by OEM's TvInputService's.
+ @hide @SystemApi -->
+ <permission android:name="android.permission.TV_INPUT_HARDWARE"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- Allows to capture a frame of TV input hardware such as
+ built-in tuners and HDMI-in's.
+ <p>Not for use by third-party applications.
+ @hide @SystemApi -->
+ <permission android:name="android.permission.CAPTURE_TV_INPUT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows TvInputService to access DVB device.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.DVB_DEVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading the OEM unlock state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows enabling/disabling OEM unlock
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.OEM_UNLOCK_STATE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows querying state of PersistentDataBlock
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.ACCESS_PDB_STATE"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows testing if a passwords is forbidden by the admins.
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.TEST_BLACKLISTED_PASSWORD"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows system update service to notify device owner about pending updates.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- =========================================== -->
+ <!-- Permissions associated with camera and image capture -->
+ <!-- =========================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi Allows disabling the transmit-indicator LED that is normally on when
+ a camera is in use by an application.
+ @hide -->
+ <permission android:name="android.permission.CAMERA_DISABLE_TRANSMIT_LED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows sending the camera service notifications about system-wide events.
+ @hide -->
+ <permission android:name="android.permission.CAMERA_SEND_SYSTEM_EVENTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows injecting the external camera to replace the internal camera.
+ @hide -->
+ <permission android:name="android.permission.CAMERA_INJECT_EXTERNAL_CAMERA"
+ android:protectionLevel="signature" />
+
+ <!-- =========================================== -->
+ <!-- Permissions associated with telephony state -->
+ <!-- =========================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi Allows granting runtime permissions to telephony related components.
+ @hide -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows modification of the telephony state - power on, mmi, etc.
+ Does not include placing calls.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MODIFY_PHONE_STATE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows read only access to precise phone state.
+ Allows reading of detailed information about phone state for special-use applications
+ such as dialers, carrier applications, or ims applications. -->
+ <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @TestApi Allows read access to privileged phone state.
+ @hide Used internally. -->
+ <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows to read device identifiers and use ICC based authentication like EAP-AKA.
+ Often required in authentication to access the carrier's server and manage services
+ of the subscriber.
+ <p>Protection level: signature|appop -->
+ <permission android:name="android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"
+ android:protectionLevel="signature|appop" />
+
+ <!-- @SystemApi Allows read access to emergency number information for ongoing calls or SMS
+ sessions.
+ @hide Used internally. -->
+ <permission android:name="android.permission.READ_ACTIVE_EMERGENCY_SESSION"
+ android:protectionLevel="signature" />
+
+ <!-- Allows listen permission to always reported system signal strength.
+ @hide Used internally. -->
+ <permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
+ corresponds to a device SIM.
+ @hide -->
+ <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_CALL_PROVIDER.
+ @hide -->
+ <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_CONNECTION_MANAGER
+ @hide -->
+ <permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.telecom.InCallService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_INCALL_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows to query ongoing call details and manage ongoing calls
+ <p>Protection level: signature|appop -->
+ <permission android:name="android.permission.MANAGE_ONGOING_CALLS"
+ android:protectionLevel="signature|appop"
+ android:label="@string/permlab_manageOngoingCalls"
+ android:description="@string/permdesc_manageOngoingCalls" />
+
+ <!-- Allows the app to request network scans from telephony.
+ <p>Not for use by third-party applications.
+ @SystemApi @hide-->
+ <permission android:name="android.permission.NETWORK_SCAN"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a link {@link android.telephony.VisualVoicemailService} to ensure that
+ only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission
+ android:name="android.permission.BIND_VISUAL_VOICEMAIL_SERVICE"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- Must be required by a {@link android.telecom.CallScreeningService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_SCREENING_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.telecom.PhoneAccountSuggestionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.telecom.CallDiagnosticService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_CALL_DIAGNOSTIC_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.telecom.CallRedirectionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_CALL_REDIRECTION_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.telecom.CallStreamingService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @SystemApi @hide-->
+ <permission android:name="android.permission.BIND_CALL_STREAMING_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.telecom.ConnectionService},
+ to ensure that only the system can bind to it.
+ @deprecated {@link android.telecom.ConnectionService}s should require
+ android.permission.BIND_TELECOM_CONNECTION_SERVICE instead.
+ @SystemApi
+ @hide -->
+ <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a
+ android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.telecom.ConnectionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to control the in-call experience.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an application to receive STK related commands.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to send EMBMS download intents to apps
+ @hide -->
+ <permission android:name="android.permission.SEND_EMBMS_INTENTS"
+ android:protectionLevel="signature|privileged" />
+
+
+ <!-- Allows internal management of the sensor framework
+ @hide -->
+ <permission android:name="android.permission.MANAGE_SENSORS"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an ImsService to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature|privileged|vendorPrivileged
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_IMS_SERVICE"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- Must be required by a telephony data service to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a NetworkService to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC)
+ through EuiccManager APIs.
+ <p>Protection level: signature|privileged|development
+ @hide
+ -->
+ <permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to
+ it.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_EUICC_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Required for reading information about carrier apps from SystemConfigManager.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.READ_CARRIER_APP_INFO"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an GbaService to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_GBA_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Required for an Application to access APIs related to RCS User Capability Exchange.
+ <p> This permission is only granted to system applications fulfilling the SMS, Dialer, and
+ Contacts app roles.
+ <p>Protection level: internal|role
+ @SystemApi
+ @hide -->
+ <permission android:name="android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE"
+ android:protectionLevel="internal|role" />
+
+ <!-- ================================== -->
+ <!-- Permissions for sdcard interaction -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- @SystemApi @TestApi Allows an application to write to internal media storage
+ @deprecated This permission is no longer honored in the system and no longer adds
+ the media_rw gid as a supplementary gid to the holder. Use the
+ android.permission.MANAGE_EXTERNAL_STORAGE instead.
+ @hide -->
+ <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to manage access to documents, usually as part
+ of a document picker.
+ <p>This permission should <em>only</em> be requested by the platform
+ document management app. This permission cannot be granted to
+ third-party apps.
+ -->
+ <permission android:name="android.permission.MANAGE_DOCUMENTS"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows an application to manage access to crates, usually as part
+ of a crates picker.
+ <p>This permission should <em>only</em> be requested by the platform
+ management app. This permission cannot be granted to
+ third-party apps.
+ @hide
+ @TestApi
+ -->
+ <permission android:name="android.permission.MANAGE_CRATES"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to cache content.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.CACHE_CONTENT"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide
+ Allows an application to aggressively allocate disk space.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.ALLOCATE_AGGRESSIVE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide
+ Allows an application to use reserved disk space.
+ <p>Not for use by third-party applications. Should only be requested by
+ apps that provide core system functionality, to ensure system stability
+ when disk is otherwise completely full.
+ -->
+ <permission android:name="android.permission.USE_RESERVED_DISK"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- ================================== -->
+ <!-- Permissions for screenlock -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows applications to disable the keyguard if it is not secure.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.DISABLE_KEYGUARD"
+ android:description="@string/permdesc_disableKeyguard"
+ android:label="@string/permlab_disableKeyguard"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to request the screen lock complexity and prompt users to update the
+ screen lock to a certain complexity level.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_PASSWORD_COMPLEXITY"
+ android:label="@string/permlab_requestPasswordComplexity"
+ android:description="@string/permdesc_requestPasswordComplexity"
+ android:protectionLevel="normal" />
+
+ <!-- ================================== -->
+ <!-- Permissions to access other installed applications -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- @deprecated No longer enforced. -->
+ <permission android:name="android.permission.GET_TASKS"
+ android:label="@string/permlab_getTasks"
+ android:description="@string/permdesc_getTasks"
+ android:protectionLevel="normal" />
+
+ <!-- New version of GET_TASKS that apps can request, since GET_TASKS doesn't really
+ give access to task information. We need this new one because there are
+ many existing apps that use add libraries and such that have validation
+ code to ensure the app has requested the GET_TASKS permission by seeing
+ if it has been granted the permission... if it hasn't, it kills the app
+ with a message about being upset. So we need to have it continue to look
+ like the app is getting that permission, even though it will never be
+ checked, and new privileged apps can now request this one for real access.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.REAL_GET_TASKS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to start a task from a ActivityManager#RecentTaskInfo.
+ @hide -->
+ <permission android:name="android.permission.START_TASKS_FROM_RECENTS"
+ android:protectionLevel="signature|privileged|recents" />
+
+ <!-- @SystemApi @hide Allows an application to call APIs that allow it to do interactions
+ across the users on the device, using singleton services and
+ user-targeted broadcasts. This permission is not available to
+ third party applications. -->
+ <permission android:name="android.permission.INTERACT_ACROSS_USERS"
+ android:protectionLevel="signature|privileged|development|role" />
+
+ <!-- @SystemApi Fuller form of {@link android.Manifest.permission#INTERACT_ACROSS_USERS}
+ that removes restrictions on where broadcasts can be sent and allows other
+ types of interactions
+ @hide -->
+ <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
+ android:protectionLevel="signature|installer|role" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+
+ <!-- Allows interaction across profiles in the same profile group. -->
+ <permission android:name="android.permission.INTERACT_ACROSS_PROFILES"
+ android:protectionLevel="signature|appop" />
+
+ <!-- @SystemApi Allows configuring apps to have the INTERACT_ACROSS_PROFILES permission so that
+ they can interact across profiles in the same profile group.
+ @hide -->
+ <permission android:name="android.permission.CONFIGURE_INTERACT_ACROSS_PROFILES"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows starting activities across profiles in the same profile group. -->
+ <permission android:name="android.permission.START_CROSS_PROFILE_ACTIVITIES"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows an application to call APIs that allow it to query and manage
+ users on the device. This permission is not available to
+ third party applications. -->
+ <permission android:name="android.permission.MANAGE_USERS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to create, remove users and get the list of
+ users on the device. Applications holding this permission can create users (including
+ normal, restricted, guest, managed, and demo users) and can optionally endow them with the
+ ephemeral property. For creating users with other kinds of properties,
+ {@link android.Manifest.permission#MANAGE_USERS} is needed.
+ This permission is not available to third party applications. -->
+ <permission android:name="android.permission.CREATE_USERS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to set user association
+ with a certain subscription. Used by Enterprise to associate a
+ subscription with a work or personal profile. -->
+ <permission android:name="android.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to call APIs that allow it to query users on the
+ device. -->
+ <permission android:name="android.permission.QUERY_USERS"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an application to access data blobs across users. -->
+ <permission android:name="android.permission.ACCESS_BLOBS_ACROSS_USERS"
+ android:protectionLevel="signature|privileged|development|role" />
+
+ <!-- @SystemApi @hide Allows an application to set the profile owners and the device owner.
+ This permission is not available to third party applications.-->
+ <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
+ android:protectionLevel="signature|role"
+ android:label="@string/permlab_manageProfileAndDeviceOwners"
+ android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+
+ <!-- @SystemApi @hide Allows an application to query device policies set by any admin on
+ the device.-->
+ <permission android:name="android.permission.QUERY_ADMIN_POLICY"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi @hide Allows an application to exempt apps from platform restrictions.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage device policy relating to time.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_TIME"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set the grant state of runtime permissions on packages.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage the identity of the managing organization.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set support messages for when a user action is affected by an
+ active policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage backup service policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BACKUP_SERVICE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage lock task policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK_TASK"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy regarding modifying applications.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_APPS_CONTROL"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage installing from unknown sources policy.
+ <p>MANAGE_SECURITY_CRITICAL_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected
+ by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage application restrictions.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_APP_RESTRICTIONS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage calling policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CALLS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage debugging features policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy preventing users from modifying users.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MODIFY_USERS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage safe boot policy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SAFE_BOOT"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to restricting a user's ability to use or
+ enable and disable the microphone.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to restricting a user's ability to use or
+ enable and disable the camera.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CAMERA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to keyguard.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_KEYGUARD"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to account management.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to hiding and suspending packages.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PACKAGE_STATE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to force set a new device unlock password or a managed profile
+ challenge on current user.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_RESET_PASSWORD"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to the status bar.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_STATUS_BAR"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to bluetooth.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BLUETOOTH"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to fun.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_FUN"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to airplane mode.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_AIRPLANE_MODE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to mobile networks.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MOBILE_NETWORK"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to physical media.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to sms.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SMS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to usb file transfers.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to lock credentials.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to Wifi.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIFI"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to screen capture.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SCREEN_CAPTURE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to input methods.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_INPUT_METHODS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to restricting the user from configuring
+ private DNS.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to the default sms application.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_DEFAULT_SMS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to profiles.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PROFILES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to interacting with profiles (e.g. Disallowing
+ cross-profile copy and paste).
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PROFILE_INTERACTION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to VPNs.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_VPN"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to audio output.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_AUDIO_OUTPUT"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to the display.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_DISPLAY"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to location.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCATION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to factory reset.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_FACTORY_RESET"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to the wallpaper.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_WALLPAPER"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to the usage of the contents of the screen.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SCREEN_CONTENT"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to system dialogs.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to users running in the background.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_RUN_IN_BACKGROUND"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to printing.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PRINTING"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to nearby communications (e.g. Beam and
+ nearby streaming).
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to windows.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_WINDOWS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to locale.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCALE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to autofill.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_AUTOFILL"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to users.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_USERS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to certificates.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CERTIFICATES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to override APNs.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_OVERRIDE_APN"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to security logging.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to system updates.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to query system updates.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_QUERY_SYSTEM_UPDATES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to private DNS.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PRIVATE_DNS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to settings.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SETTINGS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to network logging.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_NETWORK_LOGGING"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to usb data signalling.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to suspending personal apps.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SUSPEND_PERSONAL_APPS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set policy related to keeping uninstalled packages.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is
+ required to call APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_KEEP_UNINSTALLED_PACKAGES"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to accessibility.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACCESSIBILITY"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to common criteria mode.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to metered data.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_METERED_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set a network-independent global HTTP proxy.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_PROXY"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to request bugreports with user consent.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BUGREPORT"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to application user data.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_APP_USER_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to lock a profile or the device with the appropriate cross-user
+ permission.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to system apps.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_SYSTEM_APPS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to wiping data.
+ <p>{@link Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS} is required to call
+ APIs protected by this permission on users different to the calling user.
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_WIPE_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to the Memory Tagging Extension (MTE).
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MTE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to device identifiers. -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_DEVICE_IDENTIFIERS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set device policies outside the current user
+ that are critical for securing data within the current user.
+ <p>Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_*
+ permissions across all users on the device provided they are required for securing data
+ within the current user.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set device policies outside the current user
+ that are required for securing device ownership without accessing user data.
+ <p>Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_*
+ permissions across all users on the device provided they do not grant access to user
+ data. -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to set device policies outside the current user.
+ <p>Fuller form of {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS}
+ that removes the restriction on accessing user data.
+ <p>Holding this permission allows the use of any other held MANAGE_DEVICE_POLICY_*
+ permissions across all users on the device.-->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi @hide Allows an application to set a device owner on retail demo devices.-->
+ <permission android:name="android.permission.PROVISION_DEMO_DEVICE"
+ android:protectionLevel="signature|setup|knownSigner"
+ android:knownCerts="@array/demo_device_provisioning_known_signers" />
+
+ <!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
+ periods. -->
+ <permission android:name="android.permission.CLEAR_FREEZE_PERIOD"
+ android:protectionLevel="signature" />
+
+ <!-- @TestApi @hide Allows an application to force available DevicePolicyManager logs to
+ DPC. -->
+ <permission android:name="android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to write to the security log buffer in logd.
+ @hide -->
+ <permission android:name="android.permission.WRITE_SECURITY_LOG"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to get full detailed information about
+ recently running tasks, with full fidelity to the real state.
+ @hide -->
+ <permission android:name="android.permission.GET_DETAILED_TASKS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to change the Z-order of tasks.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REORDER_TASKS"
+ android:label="@string/permlab_reorderTasks"
+ android:description="@string/permdesc_reorderTasks"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi @TestApi @hide Allows an application to change to remove/kill tasks -->
+ <permission android:name="android.permission.REMOVE_TASKS"
+ android:protectionLevel="signature|recents|role" />
+
+ <!-- @deprecated Use MANAGE_ACTIVITY_TASKS instead.
+ @SystemApi @TestApi @hide Allows an application to create/manage/remove stacks -->
+ <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @TestApi @hide Allows an application to create/manage/remove tasks -->
+ <permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @SystemApi @TestApi @hide Allows an application to embed other activities -->
+ <permission android:name="android.permission.ACTIVITY_EMBEDDING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to start any activity, regardless of permission
+ protection or exported state.
+ @hide -->
+ <permission android:name="android.permission.START_ANY_ACTIVITY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to start activities from background -->
+ <permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
+ android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier|role" />
+
+ <!-- Allows an application to start foreground services from the background at any time.
+ <em>This permission is not for use by third-party applications</em>,
+ with the only exception being if the app is the default SMS app.
+ Otherwise, it's only usable by privileged apps, app verifier app, and apps with
+ any of the EMERGENCY or SYSTEM GALLERY roles.
+ -->
+ <permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"
+ android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier|role"/>
+
+ <!-- Allows an application to request interactive options when sending a broadcast.
+ @hide -->
+ <permission android:name="android.permission.BROADCAST_OPTION_INTERACTIVE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Must be required by activities that handle the intent action
+ {@link Intent#ACTION_SEND_SHOW_SUSPENDED_APP_DETAILS}. This is for use by apps that
+ hold {@link Manifest.permission#SUSPEND_APPS} to interact with the system.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS" />
+
+ <!-- Allows an application to start an activity as another app, provided that app has been
+ granted a permissionToken from the ActivityManagerService.
+ @hide -->
+ <permission android:name="android.permission.START_ACTIVITY_AS_CALLER"
+ android:protectionLevel="signature" />
+
+ <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
+ API is no longer supported. -->
+ <permission android:name="android.permission.RESTART_PACKAGES"
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
+
+ <!-- @deprecated Allows an application to call
+ {@link android.app.ActivityManager#killBackgroundProcesses}.
+ <p>As of Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ the {@link android.app.ActivityManager#killBackgroundProcesses} is no longer available to
+ third party applications. For backwards compatibility, the background processes of the
+ caller's own package will still be killed when calling this API, meanwhile this permission
+ is not required anymore in this case.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi @hide Allows an application to call
+ {@link android.app.ActivityManager#killBackgroundProcesses}
+ to kill background processes of other apps.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.KILL_ALL_BACKGROUND_PROCESSES"
+ android:label="@string/permlab_killBackgroundProcesses"
+ android:description="@string/permdesc_killBackgroundProcesses"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to query process states and current
+ OOM adjustment scores.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows use of PendingIntent.getIntent(), .
+ @hide @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)
+ -->
+ <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
+ android:protectionLevel="signature" />
+
+ <!-- ================================== -->
+ <!-- Permissions affecting the display of other applications -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows an app to create windows using the type
+ {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
+ shown on top of all other apps. Very few apps
+ should use this permission; these windows are intended for
+ system-level interaction with the user.
+
+ <p class="note"><strong>Note:</strong> If the app
+ targets API level 23 or higher, the app user must explicitly grant
+ this permission to the app through a permission management screen. The app requests
+ the user's approval by sending an intent with action
+ {@link android.provider.Settings#ACTION_MANAGE_OVERLAY_PERMISSION}.
+ The app can check whether it has this authorization by calling
+ {@link android.provider.Settings#canDrawOverlays
+ Settings.canDrawOverlays()}.
+ <p>Protection level: signature|setup|appop|installer|pre23|development -->
+ <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
+ android:label="@string/permlab_systemAlertWindow"
+ android:description="@string/permdesc_systemAlertWindow"
+ android:protectionLevel="signature|setup|appop|installer|pre23|development" />
+
+ <!-- @SystemApi @hide Allows an application to create windows using the type
+ {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
+ shown on top of all other apps.
+
+ Allows an application to use
+ {@link android.view.WindowManager.LayoutsParams#setSystemApplicationOverlay(boolean)}
+ to create overlays that will stay visible, even if another window is requesting overlays to
+ be hidden through {@link android.view.Window#setHideOverlayWindows(boolean)}.
+
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"
+ android:protectionLevel="signature|recents|role|installer"/>
+
+ <!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
+ @hide
+ -->
+ <permission android:name="android.permission.RUN_IN_BACKGROUND"
+ android:label="@string/permlab_runInBackground"
+ android:description="@string/permdesc_runInBackground"
+ android:protectionLevel="signature" />
+
+ <!-- @deprecated Use
+ {@link android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND}
+ @hide
+ -->
+ <permission android:name="android.permission.USE_DATA_IN_BACKGROUND"
+ android:label="@string/permlab_useDataInBackground"
+ android:description="@string/permdesc_useDataInBackground"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to set display offsets for the screen.
+ This permission is not available to third party applications. -->
+ <permission android:name="android.permission.SET_DISPLAY_OFFSET"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows a companion app to run in the background. This permission implies
+ {@link android.Manifest.permission#REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND},
+ and allows to start a foreground service from the background.
+ If an app does not have to run in the background, but only needs to start a foreground
+ service from the background, consider using
+ {@link android.Manifest.permission#REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND},
+ which is less powerful.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND"
+ android:label="@string/permlab_runInBackground"
+ android:description="@string/permdesc_runInBackground"
+ android:protectionLevel="normal" />
+
+ <!-- Allows a companion app to start a foreground service from the background.
+ {@see android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND"
+ android:protectionLevel="normal"/>
+
+ <!-- Allows a companion app to use data in the background.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND"
+ android:label="@string/permlab_useDataInBackground"
+ android:description="@string/permdesc_useDataInBackground"
+ android:protectionLevel="normal" />
+
+ <!-- Allows app to request to be associated with a device via
+ {@link android.companion.CompanionDeviceManager}
+ as a "watch"
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_WATCH"
+ android:protectionLevel="normal" />
+
+ <!-- Allows app to request to be associated with a device via
+ {@link android.companion.CompanionDeviceManager}
+ as "glasses"
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_GLASSES"
+ android:protectionLevel="normal" />
+
+ <!-- Allows application to request to be associated with a virtual display capable of streaming
+ Android applications
+ ({@link android.companion.AssociationRequest#DEVICE_PROFILE_APP_STREAMING})
+ by {@link android.companion.CompanionDeviceManager}.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows application to request to be associated with a virtual device associated to a
+ nearby device capable of rendering an entire OS
+ ({@link android.companion.AssociationRequest#DEVICE_PROFILE_NEARBY_DEVICE_STREAMING})
+ by {@link android.companion.CompanionDeviceManager}.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_NEARBY_DEVICE_STREAMING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows application to request to be associated with a vehicle head unit capable of
+ automotive projection
+ ({@link android.companion.AssociationRequest#DEVICE_PROFILE_AUTOMOTIVE_PROJECTION})
+ by {@link android.companion.CompanionDeviceManager}.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows application to request to be associated with a computer to share functionality
+ and/or data with other devices, such as notifications, photos and media
+ ({@link android.companion.AssociationRequest#DEVICE_PROFILE_COMPUTER})
+ by {@link android.companion.CompanionDeviceManager}.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_COMPUTER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to create a "self-managed" association.
+ -->
+ <permission android:name="android.permission.REQUEST_COMPANION_SELF_MANAGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows a companion app to associate to Wi-Fi.
+ <p>Only for use by a single pre-approved app.
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an app to read and listen to projection state.
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.READ_PROJECTION_STATE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an app to set and release automotive projection.
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.TOGGLE_AUTOMOTIVE_PROJECTION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an app to prevent non-system-overlay windows from being drawn on top of it -->
+ <permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"
+ android:protectionLevel="normal" />
+
+ <!-- ================================== -->
+ <!-- Permissions affecting the system wallpaper -->
+ <!-- ================================== -->
+ <eat-comment />
+
+ <!-- Allows applications to set the wallpaper.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.SET_WALLPAPER"
+ android:label="@string/permlab_setWallpaper"
+ android:description="@string/permdesc_setWallpaper"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to set the wallpaper hints.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.SET_WALLPAPER_HINTS"
+ android:label="@string/permlab_setWallpaperHints"
+ android:description="@string/permdesc_setWallpaperHints"
+ android:protectionLevel="normal" />
+
+ <!-- Allow the app to read the system wallpaper image without
+ holding the READ_EXTERNAL_STORAGE permission.
+ <p>Not for use by third-party applications.
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.READ_WALLPAPER_INTERNAL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allow apps to always update wallpaper by sending data.
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.ALWAYS_UPDATE_WALLPAPER"
+ android:protectionLevel="internal|role" />
+
+ <!-- ===================================================== -->
+ <!-- Permissions for changing the system clock / time zone -->
+ <!-- ===================================================== -->
+ <eat-comment />
+
+ <!-- Allows applications to set the system time directly.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_TIME"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows applications to set the system time zone directly.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.SET_TIME_ZONE"
+ android:label="@string/permlab_setTimeZone"
+ android:description="@string/permdesc_setTimeZone"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows telephony to suggest the time / time zone.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SUGGEST_MANUAL_TIME_AND_ZONE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows system clock time suggestions from an external clock / time source to be made.
+ The nature of "external" could be highly form-factor specific. Example, times
+ obtained via the VHAL for Android Auto OS.
+ <p>Not for use by third-party applications.
+ @SystemApi @hide
+ -->
+ <permission android:name="android.permission.SUGGEST_EXTERNAL_TIME"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows applications like settings to manage configuration associated with automatic time
+ and time zone detection.
+ <p>Not for use by third-party applications.
+ @SystemApi @hide
+ -->
+ <permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- ==================================================== -->
+ <!-- Permissions related to changing status bar -->
+ <!-- ==================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to expand or collapse the status bar.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.EXPAND_STATUS_BAR"
+ android:label="@string/permlab_expandStatusBar"
+ android:description="@string/permdesc_expandStatusBar"
+ android:protectionLevel="normal" />
+
+ <!-- ============================================================== -->
+ <!-- Permissions related to adding/removing shortcuts from Launcher -->
+ <!-- ============================================================== -->
+ <eat-comment />
+
+ <!-- Allows an application to install a shortcut in Launcher.
+ <p>In Android O (API level 26) and higher, the <code>INSTALL_SHORTCUT</code> broadcast no
+ longer has any effect on your app because it's a private, implicit
+ broadcast. Instead, you should create an app shortcut by using the
+ {@link android.content.pm.ShortcutManager#requestPinShortcut requestPinShortcut()}
+ method from the {@link android.content.pm.ShortcutManager} class.
+ <p>Protection level: normal
+ -->
+ <permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
+ android:label="@string/permlab_install_shortcut"
+ android:description="@string/permdesc_install_shortcut"
+ android:protectionLevel="normal"/>
+
+ <!-- <p class="caution"><strong>Don't use this permission in your app.</strong><br>This
+ permission is no longer supported.
+ -->
+ <permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
+ android:label="@string/permlab_uninstall_shortcut"
+ android:description="@string/permdesc_uninstall_shortcut"
+ android:protectionLevel="normal"/>
+
+ <!-- ==================================================== -->
+ <!-- Permissions related to accessing sync settings -->
+ <!-- ==================================================== -->
+ <eat-comment />
+
+ <!-- Allows applications to read the sync settings.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.READ_SYNC_SETTINGS"
+ android:description="@string/permdesc_readSyncSettings"
+ android:label="@string/permlab_readSyncSettings"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to write the sync settings.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.WRITE_SYNC_SETTINGS"
+ android:description="@string/permdesc_writeSyncSettings"
+ android:label="@string/permlab_writeSyncSettings"
+ android:protectionLevel="normal" />
+
+ <!-- Allows applications to read the sync stats.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.READ_SYNC_STATS"
+ android:description="@string/permdesc_readSyncStats"
+ android:label="@string/permlab_readSyncStats"
+ android:protectionLevel="normal" />
+
+ <!-- ============================================ -->
+ <!-- Permissions for low-level system interaction -->
+ <!-- ============================================ -->
+ <eat-comment />
+
+ <!-- @SystemApi @hide Change the screen compatibility mode of applications -->
+ <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to modify the current configuration, such
+ as locale.
+ <p>Protection level: signature|privileged|development -->
+ <permission android:name="android.permission.CHANGE_CONFIGURATION"
+ android:protectionLevel="signature|privileged|development|role" />
+
+ <!-- Allows an application to read or write the system settings.
+
+ <p class="note"><strong>Note:</strong> If the app targets API level 23
+ or higher, the app user
+ must explicitly grant this permission to the app through a permission management screen.
+ The app requests the user's approval by sending an intent with action
+ {@link android.provider.Settings#ACTION_MANAGE_WRITE_SETTINGS}. The app
+ can check whether it has this authorization by calling {@link
+ android.provider.Settings.System#canWrite Settings.System.canWrite()}.
+
+ <p>Protection level: signature|preinstalled|appop|pre23
+ -->
+ <permission android:name="android.permission.WRITE_SETTINGS"
+ android:label="@string/permlab_writeSettings"
+ android:description="@string/permdesc_writeSettings"
+ android:protectionLevel="signature|preinstalled|appop|pre23|role" />
+
+ <!-- Allows an application to modify the Google service map.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WRITE_GSERVICES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @TestApi @hide Allows an application to modify config settings.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WRITE_DEVICE_CONFIG"
+ android:protectionLevel="signature|verifier|configurator"/>
+
+ <!-- @SystemApi @hide Allows an application to read config settings.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_DEVICE_CONFIG"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- @SystemApi @TestApi @hide Allows an application to modify only allowlisted settings.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG"
+ android:protectionLevel="signature|verifier|configurator"/>
+
+ <!-- @SystemApi @TestApi @hide Allows an application to read/write sync disabled mode config.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG"
+ android:protectionLevel="signature|verifier|configurator"/>
+
+ <!-- @SystemApi @hide Allows applications like settings to read system-owned
+ application-specific locale configs.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide Allows applications to set an application-specific {@link LocaleConfig}.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_APP_SPECIFIC_LOCALECONFIG"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to monitor {@link android.provider.Settings.Config} access.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
+ android:protectionLevel="signature"/>
+
+ <!-- @SystemApi @TestApi Allows an application to call
+ {@link android.app.ActivityManager#forceStopPackage}.
+ @hide -->
+ <permission android:name="android.permission.FORCE_STOP_PACKAGES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to retrieve the content of the active window
+ An active window is the window that has fired an accessibility event. -->
+ <permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Modify the global animation scaling factor.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_ANIMATION_SCALE"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @deprecated This functionality will be removed in the future; please do
+ not use. Allow an application to make its activities persistent. -->
+ <permission android:name="android.permission.PERSISTENT_ACTIVITY"
+ android:label="@string/permlab_persistentActivity"
+ android:description="@string/permdesc_persistentActivity"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to find out the space used by any package.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.GET_PACKAGE_SIZE"
+ android:label="@string/permlab_getPackageSize"
+ android:description="@string/permdesc_getPackageSize"
+ android:protectionLevel="normal" />
+
+ <!-- @deprecated No longer useful, see
+ {@link android.content.pm.PackageManager#addPackageToPreferred}
+ for details. -->
+ <permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- Allows an application to receive the
+ {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
+ broadcast after the system finishes booting. If you don't
+ request this permission, you will not receive the broadcast at
+ that time. Though holding this permission does not have any
+ security implications, it can have a negative impact on the
+ user experience by increasing the amount of time it takes the
+ system to start and allowing applications to have themselves
+ running without the user being aware of them. As such, you must
+ explicitly declare your use of this facility to make that visible
+ to the user.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
+ android:label="@string/permlab_receiveBootCompleted"
+ android:description="@string/permdesc_receiveBootCompleted"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to broadcast sticky intents. These are
+ broadcasts whose data is held by the system after being finished,
+ so that clients can quickly retrieve that data without having
+ to wait for the next broadcast.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.BROADCAST_STICKY"
+ android:label="@string/permlab_broadcastSticky"
+ android:description="@string/permdesc_broadcastSticky"
+ android:protectionLevel="normal" />
+
+ <!-- Allows mounting and unmounting file systems for removable storage.
+ <p>Not for use by third-party applications.-->
+ <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows formatting file systems for removable storage.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide -->
+ <permission android:name="android.permission.STORAGE_INTERNAL"
+ android:protectionLevel="signature" />
+
+ <!-- Allows access to ASEC non-destructive API calls
+ @hide -->
+ <permission android:name="android.permission.ASEC_ACCESS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows creation of ASEC volumes
+ @hide -->
+ <permission android:name="android.permission.ASEC_CREATE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows destruction of ASEC volumes
+ @hide -->
+ <permission android:name="android.permission.ASEC_DESTROY"
+ android:protectionLevel="signature" />
+
+ <!-- Allows mount / unmount of ASEC volumes
+ @hide -->
+ <permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows rename of ASEC volumes
+ @hide -->
+ <permission android:name="android.permission.ASEC_RENAME"
+ android:protectionLevel="signature" />
+
+ <!-- Allows applications to write the apn settings and read sensitive fields of
+ an existing apn settings like user and password.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WRITE_APN_SETTINGS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows applications to change network connectivity state.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CHANGE_NETWORK_STATE"
+ android:description="@string/permdesc_changeNetworkState"
+ android:label="@string/permlab_changeNetworkState"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to clear the caches of all installed
+ applications on the device.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.CLEAR_APP_CACHE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to use any media decoder when decoding for playback
+ @hide -->
+ <permission android:name="android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to install and/or uninstall CA certificates on
+ behalf of the user.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_CA_CERTIFICATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to do certain operations needed for
+ interacting with the recovery (system update) system.
+ @hide -->
+ <permission android:name="android.permission.RECOVERY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to do certain operations needed for
+ resume on reboot feature.
+ @hide -->
+ <permission android:name="android.permission.BIND_RESUME_ON_REBOOT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to read system update info.
+ @hide -->
+ <permission android:name="android.permission.READ_SYSTEM_UPDATE_INFO"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows the system to bind to an application's task services
+ @hide -->
+ <permission android:name="android.permission.BIND_JOB_SERVICE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_JOB_SERVICE"/>
+
+ <!-- Allows an application to initiate configuration updates
+ <p>An application requesting this permission is responsible for
+ verifying the source and integrity of any update before passing
+ it off to the various individual installer components
+ @hide -->
+ <permission android:name="android.permission.UPDATE_CONFIG"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to query the current time zone rules state
+ on device.
+ @SystemApi @hide -->
+ <permission android:name="android.permission.QUERY_TIME_ZONE_RULES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows a time zone rule updater application to request
+ the system installs / uninstalls timezone rules.
+ <p>An application requesting this permission is responsible for
+ verifying the source and integrity of the update before passing
+ it off to the installer components.
+ @SystemApi @hide -->
+ <permission android:name="android.permission.UPDATE_TIME_ZONE_RULES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows the system to reset throttling in shortcut manager.
+ @hide -->
+ <permission android:name="android.permission.RESET_SHORTCUT_MANAGER_THROTTLING"
+ android:protectionLevel="signature" />
+
+ <!-- Allows the system to bind to the discovered Network Recommendation Service.
+ @SystemApi @hide -->
+ <permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
+
+ <!-- Allows an application to enable, disable and change priority of
+ runtime resource overlays.
+ @hide -->
+ <permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to set, update and remove the credential management app.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP"
+ android:protectionLevel="signature" />
+
+ <!-- Allows a font updater application to request that the system installs/uninstalls/updates
+ font files. @SystemApi @hide -->
+ <permission android:name="android.permission.UPDATE_FONTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to use the AttestationVerificationService.
+ @hide -->
+ <permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to export a AttestationVerificationService to verify attestations on
+ behalf of AttestationVerificationManager for system-defined attestation profiles.
+ @hide -->
+ <permission android:name="android.permission.VERIFY_ATTESTATION"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by any AttestationVerificationService to ensure that only the system can
+ bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows the caller to generate keymint keys with the INCLUDE_UNIQUE_ID tag, which
+ uniquely identifies the device via the attestation certificate.
+ @hide @TestApi -->
+ <permission android:name="android.permission.REQUEST_UNIQUE_ID_ATTESTATION"
+ android:protectionLevel="signature" />
+
+ <!-- ========================================= -->
+ <!-- Permissions for special development tools -->
+ <!-- ========================================= -->
+ <eat-comment />
+
+ <!-- Allows an application to read or write the secure system settings.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WRITE_SECURE_SETTINGS"
+ android:protectionLevel="signature|privileged|development|role|installer" />
+
+ <!-- Allows an application to retrieve state dump information from system services.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.DUMP"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to start tracing for InputMethod and WindowManager.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_UI_TRACING"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to read the low-level system log files.
+ <p>Not for use by third-party applications, because
+ Log entries can contain the user's private information. -->
+ <permission android:name="android.permission.READ_LOGS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Configure an application for debugging.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_DEBUG_APP"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to set the maximum number of (not needed)
+ application processes that can be running.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_PROCESS_LIMIT"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to control whether activities are immediately
+ finished when put in the background.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_ALWAYS_FINISH"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allow an application to request that a signal be sent to all persistent processes.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @hide @SystemApi Must be required by a
+ {@link com.android.service.tracing.TraceReportService}, to ensure that only the system
+ can bind to it.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.BIND_TRACE_REPORT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @SystemApi @TestApi
+ Allow an application to approve incident and bug reports to be
+ shared off-device. There can be only one application installed on the
+ device with this permission, and since this is a privileged permission, it
+ must be in priv-app.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.APPROVE_INCIDENT_REPORTS"
+ android:protectionLevel="signature|incidentReportApprover" />
+
+ <!-- @hide Allow an application to approve an incident or bug report approval from
+ the system. -->
+ <permission android:name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- ==================================== -->
+ <!-- Private permissions -->
+ <!-- ==================================== -->
+ <eat-comment />
+
+ <!-- Allows access to the list of accounts in the Accounts Service.
+ <p>Protection level: signature|privileged -->
+ <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows but does not guarantee access to user passwords at the conclusion of add account
+ @hide -->
+ <permission android:name="android.permission.GET_PASSWORD"
+ android:protectionLevel="signature" />
+
+ <!-- Allows applications to RW to diagnostic resources.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.DIAGNOSTIC"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to open, close, or disable the status bar
+ and its icons.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.STATUS_BAR"
+ android:protectionLevel="signature|privileged|recents" />
+
+ <!-- Allows an application to trigger bugreport via shell using the bugreport API.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.TRIGGER_SHELL_BUGREPORT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to trigger profcollect report upload via shell.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.TRIGGER_SHELL_PROFCOLLECT_UPLOAD"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to be the status bar. Currently used only by SystemUI.apk
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.STATUS_BAR_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to bind to third party quick settings tiles.
+ <p>Should only be requested by the System, should be required by
+ TileService declarations.-->
+ <permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE"
+ android:protectionLevel="signature|recents" />
+
+ <!-- Allows SystemUI to request third party controls.
+ <p>Should only be requested by the System and required by
+ {@link android.service.controls.ControlsProviderService} declarations.
+ -->
+ <permission android:name="android.permission.BIND_CONTROLS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to force a BACK operation on whatever is the
+ top activity.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.FORCE_BACK"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to update device statistics.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.UPDATE_DEVICE_STATS"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi @hide Allows an application to collect application operation statistics.
+ Not for use by third party apps. -->
+ <permission android:name="android.permission.GET_APP_OPS_STATS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @SystemApi @hide Allows an application to collect historical application operation
+ statistics.
+ <p>Not for use by third party applications.
+ -->
+ <permission android:name="android.permission.GET_HISTORICAL_APP_OPS_STATS"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Allows an application to update application operation statistics. Not for
+ use by third party apps.
+ @hide -->
+ <permission android:name="android.permission.UPDATE_APP_OPS_STATS"
+ android:protectionLevel="signature|privileged|installer|role" />
+
+ <!-- @SystemApi Allows an application to update the user app op restrictions.
+ Not for use by third party apps.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_APP_OPS_RESTRICTIONS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- Allows an application to update the user app op modes.
+ Not for use by third party apps.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_APP_OPS_MODES"
+ android:protectionLevel="signature|installer|verifier|role" />
+
+ <!-- @SystemApi Allows an application to open windows that are for use by parts
+ of the system user interface.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
+ android:protectionLevel="signature|module" />
+
+ <!-- Allows an application to avoid all toast rate limiting restrictions.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.UNLIMITED_TOASTS"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.UNLIMITED_TOASTS" />
+
+ <!-- @SystemApi Allows an application to use
+ {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
+ to hide non-system-overlay windows.
+ <p>Not for use by third-party applications.
+ @deprecated Use {@link android.Manifest.permission#HIDE_OVERLAY_WINDOWS} instead
+ @hide
+ -->
+ <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- @SystemApi Allows an application to manage (create, destroy,
+ Z-order) application tokens in the window manager.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_APP_TOKENS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows System UI to register listeners for events from Window Manager.
+ @hide -->
+ <permission android:name="android.permission.REGISTER_WINDOW_MANAGER_LISTENERS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows the application to temporarily freeze the screen for a
+ full-screen transition. -->
+ <permission android:name="android.permission.FREEZE_SCREEN"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to inject user events (keys, touch, trackball)
+ into the event stream and deliver them to ANY window. Without this
+ permission, you can only deliver events to windows in your own process.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.INJECT_EVENTS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to register an input filter which filters the stream
+ of user events (keys, touch, trackball) before they are dispatched to any window. -->
+ <permission android:name="android.permission.FILTER_EVENTS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
+ <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to modify accessibility information from another app. -->
+ <permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to perform accessibility operations (e.g. send events) on
+ behalf of another package. -->
+ <permission android:name="android.permission.ACT_AS_PACKAGE_FOR_ACCESSIBILITY"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to change the accessibility volume. -->
+ <permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to collect frame statistics -->
+ <permission android:name="android.permission.FRAME_STATS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to temporary enable accessibility on the device. -->
+ <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to launch detail settings activity of a particular
+ accessibility service.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @SystemApi Allows an application to watch and control how activities are
+ started globally in the system. Only for is in debugging
+ (usually the monkey command).
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SET_ACTIVITY_WATCHER"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to call the activity manager shutdown() API
+ to put the higher-level system there into a shutdown state.
+ @hide -->
+ <permission android:name="android.permission.SHUTDOWN"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to tell the activity manager to temporarily
+ stop application switches, putting it into a special mode that
+ prevents applications from immediately switching away from some
+ critical UI such as the home screen.
+ @hide -->
+ <permission android:name="android.permission.STOP_APP_SWITCHES"
+ android:protectionLevel="signature|privileged|recents" />
+
+ <!-- @SystemApi Allows an application to retrieve private information about
+ the current top activity, such as any assist context it can provide.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @SystemApi Allows an application to set the system audio caption and its UI
+ enabled state.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows an application to retrieve the current state of keys and
+ switches.
+ <p>Not for use by third-party applications.
+ @deprecated The API that used this permission has been removed. -->
+ <permission android:name="android.permission.READ_INPUT_STATE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.inputmethodservice.InputMethodService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_INPUT_METHOD"
+ android:protectionLevel="signature" />
+
+ <!-- Allows access to Test APIs defined in {@link android.view.inputmethod.InputMethodManager}.
+ @hide -->
+ <permission android:name="android.permission.TEST_INPUT_METHOD"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.media.midi.MidiDeviceService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_MIDI_DEVICE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.accessibilityservice.AccessibilityService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.printservice.PrintService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_PRINT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
+ to ensure that only the system can bind to it.
+ @hide
+ @SystemApi
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows applications to get the installed and enabled print services.
+ @hide
+ @SystemApi
+ <p>Protection level: signature|preinstalled
+ -->
+ <permission android:name="android.permission.READ_PRINT_SERVICES"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- Allows applications to get the currently recommended print services for printers.
+ @hide
+ @SystemApi
+ <p>Protection level: signature|preinstalled
+ -->
+ <permission android:name="android.permission.READ_PRINT_SERVICE_RECOMMENDATIONS"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
+ or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
+ the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_NFC_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.service.quickaccesswallet.QuickAccessWalletService}
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by the CompanionDeviceManager to ensure that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by any
+ {@link android.companion.CompanionDeviceService}s
+ to ensure that only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_COMPANION_DEVICE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
+ that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a TextService (e.g. SpellCheckerService)
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_TEXT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be required by a AttentionService
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_ATTENTION_SERVICE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_ATTENTION_SERVICE" />
+
+ <!-- @SystemApi Must be required by a RotationResolverService
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_ROTATION_RESOLVER_SERVICE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.BIND_ROTATION_RESOLVER_SERVICE" />
+
+ <!-- @SystemApi Allows an application to access ambient context service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"
+ android:protectionLevel="signature|privileged|role"/>
+
+ <!-- @SystemApi Required by a AmbientContextEventDetectionService
+ to ensure that only the service with this permission can bind to it.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.BIND_AMBIENT_CONTEXT_DETECTION_SERVICE"
+ android:protectionLevel="signature"/>
+
+ <!-- @SystemApi Required by a WearableSensingService to
+ ensure that only the caller with this permission can bind to it.
+ <p> Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_WEARABLE_SENSING_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an app to manage the wearable sensing service.
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_WEARABLE_SENSING_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.net.VpnService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_VPN_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.service.wallpaper.WallpaperService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_WALLPAPER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a game service to ensure that only the
+ system can bind to it.
+ <p>Protection level: signature
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_GAME_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_VOICE_INTERACTION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be required by a {@link android.service.voice.HotwordDetectionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be required by a {@link android.service.voice.visualQueryDetection},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE"
+ android:protectionLevel="signature" />
+
+
+ <!-- @SystemApi Allows an application to manage hotword detection and visual query detection
+ on the device.
+ <p>Protection level: internal|preinstalled
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.MANAGE_HOTWORD_DETECTION"
+ android:protectionLevel="internal|preinstalled" />
+
+ <!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
+ <p>Protection level: signature|role
+ <p>Intended for use by ROLE_ASSISTANT and signature apps only.
+ -->
+ <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE"
+ android:protectionLevel="signature|role"/>
+
+ <!-- Must be required by a {@link android.service.credentials.CredentialProviderService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_CREDENTIAL_PROVIDER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.service.autofill.AutofillService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a
+ {@link android.service.assist.classification.FieldClassificationService},
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_FIELD_CLASSIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Alternative version of android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE.
+ This permission was renamed during the O previews but it was supported on the final O
+ release, so we need to carry it over.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_AUTOFILL"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.service.autofill.AutofillFieldClassificationService}
+ to ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.service.autofill.InlineSuggestionRenderService}
+ to ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_INLINE_SUGGESTION_RENDER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.textclassifier.TextClassifierService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_TEXTCLASSIFIER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a
+ {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService}
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.selectiontoolbar.SelectionToolbarRenderService,
+ to ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_SELECTION_TOOLBAR_RENDER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.contentcapture.ContentCaptureService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_CONTENT_CAPTURE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.translation.TranslationService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_TRANSLATION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows apps to use ui translation functions.
+ <p>Protection level: signature|privileged
+ @hide Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.MANAGE_UI_TRANSLATION"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Must be required by a android.service.contentsuggestions.ContentSuggestionsService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_CONTENT_SUGGESTIONS_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be declared by a android.service.musicrecognition.MusicRecognitionService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_MUSIC_RECOGNITION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a android.service.autofill.augmented.AugmentedAutofillService,
+ to ensure that only the system can bind to it.
+ @SystemApi @hide This is not a third-party API (intended for OEMs and system apps).
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.service.voice.VoiceInteractionService} implementation
+ to enroll its own sound models. This is a more restrictive permission than the higher-level
+ permission KEYPHRASE_ENROLLMENT_APPLICATION. For the caller to enroll sound models with
+ this permission, it must hold the permission and be the active VoiceInteractionService in
+ the system.
+ {@see Settings.Secure.VOICE_INTERACTION_SERVICE}
+ @hide -->
+ <permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a keyphrase enrollment application, to enroll sound models. This is
+ treated as a higher-level permission to MANAGE_VOICE_KEYPHRASES as a caller can enroll
+ sound models at any time. This permission should be reserved for system enrollment
+ applications detected by {@link android.hardware.soundtrigger.KeyphraseEnrollmentInfo}
+ only.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.KEYPHRASE_ENROLLMENT_APPLICATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
+ to ensure that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_REMOTE_DISPLAY"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.media.tv.TvInputService}
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_TV_INPUT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.media.tv.interactive.TvInteractiveAppService}
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_TV_INTERACTIVE_APP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi
+ Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ <p>Not for use by third-party applications. </p>
+ @hide -->
+ <permission android:name="android.permission.BIND_TV_REMOTE_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows TV input apps and TV apps to use TIS extension interfaces for
+ domain-specific features.
+ <p>Protection level: signature|privileged|vendorPrivileged
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.TIS_EXTENSION_INTERFACE"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- @SystemApi
+ Must be required for a virtual remote controller for TV.
+ <p>Protection level: signature|privileged
+ <p>Not for use by third-party applications. </p>
+ @hide -->
+ <permission android:name="android.permission.TV_VIRTUAL_REMOTE_CONTROLLER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to change HDMI CEC active source.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to modify parental controls
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to read TvContentRatingSystemInfo
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.READ_CONTENT_RATING_SYSTEMS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to notify TV inputs by sending broadcasts.
+ <p>Protection level: signature|privileged
+ <p>Not for use by third-party applications.
+ @hide @SystemApi -->
+ <permission android:name="android.permission.NOTIFY_TV_INPUTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- This permission is required among systems services when accessing
+ tuner resource management related APIs or information.
+ <p>Protection level: signature|privileged|vendorPrivileged
+ <p>This should only be used by the OEM TvInputService.
+ @hide -->
+ <permission android:name="android.permission.TUNER_RESOURCE_ACCESS"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- @SystemApi This permission is required by Media Resource Manager Service when
+ system services create MediaCodecs on behalf of other processes and apps.
+ <p>Protection level: signature
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MEDIA_RESOURCE_OVERRIDE_PID"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+ <uses-permission android:name="android.permission.MEDIA_RESOURCE_OVERRIDE_PID" />
+
+ <!-- This permission is required by Media Resource Observer Service when
+ accessing its registerObserver Api.
+ <p>Protection level: signature|privileged
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by a {@link android.media.routing.MediaRouteService}
+ to ensure that only the system can interact with it.
+ @hide -->
+ <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by device administration receiver, to ensure that only the
+ system can interact with it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_DEVICE_ADMIN"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Required to add or remove another application as a device admin.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_DEVICE_ADMINS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an app to reset the device password.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RESET_PASSWORD"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an app to lock the device.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.LOCK_DEVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows low-level access to setting the orientation (actually
+ rotation) of the screen.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SET_ORIENTATION"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @SystemApi Allows low-level access to setting the pointer speed.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.SET_POINTER_SPEED"
+ android:protectionLevel="signature" />
+
+ <!-- Allows low-level access to setting input device calibration.
+ <p>Not for use by normal applications.
+ @hide -->
+ <permission android:name="android.permission.SET_INPUT_CALIBRATION"
+ android:protectionLevel="signature" />
+
+ <!-- Allows low-level access to setting the keyboard layout.
+ <p>Not for use by third-party applications.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows low-level access for re-mapping modifier keys.
+ <p>Not for use by third-party applications.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.REMAP_MODIFIER_KEYS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows low-level access for monitoring keyboard backlight changes.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MONITOR_KEYBOARD_BACKLIGHT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an app to schedule a prioritized alarm that can be used to perform
+ background work even when the device is in doze.
+ <p>Not for use by third-party applications.
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.SCHEDULE_PRIORITIZED_ALARM"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- Allows applications to use exact alarm APIs.
+ <p>Exact alarms should only be used for user-facing features.
+ For more details, see <a
+ href="{@docRoot}about/versions/12/behavior-changes-12#exact-alarm-permission">
+ Exact alarm permission</a>.
+ <p>Apps who hold this permission and target API level 31 or above, always stay in the
+ {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_WORKING_SET WORKING_SET} or
+ lower standby bucket.
+ Applications targeting API level 30 or below do not need this permission to use
+ exact alarm APIs.
+ -->
+ <permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
+ android:protectionLevel="signature|privileged|appop"/>
+
+ <!-- Allows apps to use exact alarms just like with SCHEDULE_EXACT_ALARM but without needing
+ to request this permission from the user.
+ <p><b>This is only for apps that rely on exact alarms for their core functionality.</b>
+ App stores may enforce policies to audit and review the use of this permission. Any app that
+ requests this but is found to not require exact alarms for its primary function may be
+ removed from the app store.
+ -->
+ <permission android:name="android.permission.USE_EXACT_ALARM"
+ android:protectionLevel="normal"/>
+
+ <!-- Allows an application to query tablet mode state and monitor changes
+ in it.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.TABLET_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to request installing packages. Apps
+ targeting APIs greater than 25 must hold this permission in
+ order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
+ android:label="@string/permlab_requestInstallPackages"
+ android:description="@string/permdesc_requestInstallPackages"
+ android:protectionLevel="signature|appop" />
+
+ <!-- Allows an application to request deleting packages. Apps
+ targeting APIs {@link android.os.Build.VERSION_CODES#P} or greater must hold this
+ permission in order to use {@link android.content.Intent#ACTION_UNINSTALL_PACKAGE} or
+ {@link android.content.pm.PackageInstaller#uninstall}.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.REQUEST_DELETE_PACKAGES"
+ android:label="@string/permlab_requestDeletePackages"
+ android:description="@string/permdesc_requestDeletePackages"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to install packages.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.INSTALL_PACKAGES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to install self updates. This is a limited version
+ of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.INSTALL_SELF_UPDATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to install updates. This is a limited version
+ of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.INSTALL_PACKAGE_UPDATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to install existing system packages. This is a limited
+ version of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ <p>Not for use by third-party applications.
+ TODO(b/80204953): remove this permission once we have a long-term solution.
+ @hide
+ -->
+ <permission android:name="com.android.permission.INSTALL_EXISTING_PACKAGES"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an application to use the package installer v2 APIs.
+ <p>The package installer v2 APIs are still a work in progress and we're
+ currently validating they work in all scenarios.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="com.android.permission.USE_INSTALLER_V2"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @TestApi Allows a testOnly application to get installed.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.INSTALL_TEST_ONLY_PACKAGE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to install DPCs only, an application is
+ considered a DPC if it has a {@link android.app.admin.DeviceAdminReceiver}
+ protected by {@link android.Manifest.permission#BIND_DEVICE_ADMIN).
+ This is a limited version of
+ {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ @hide
+ -->
+ <permission android:name="android.permission.INSTALL_DPC_PACKAGES"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to read resolved paths to the APKs (Base and any splits)
+ of a session based install.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS"
+ android:protectionLevel="signature|installer" />
+ <uses-permission android:name="android.permission.READ_INSTALLED_SESSION_PATHS" />
+
+ <!-- Allows an application to use System Data Loaders.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @TestApi Allows an application to clear user data.
+ <p>Not for use by third-party applications
+ @hide
+ -->
+ <permission android:name="android.permission.CLEAR_APP_USER_DATA"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide Allows an application to get the URI permissions
+ granted to another application.
+ <p>Not for use by third-party applications
+ -->
+ <permission android:name="android.permission.GET_APP_GRANTED_URI_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to clear the URI permissions
+ granted to another application.
+ <p>Not for use by third-party applications
+ -->
+ <permission
+ android:name="android.permission.CLEAR_APP_GRANTED_URI_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide
+ Allows an application to change the status of Scoped Access Directory requests granted or
+ rejected by the user.
+ <p>This permission should <em>only</em> be requested by the platform
+ settings app. This permission cannot be granted to third-party apps.
+ <p>Protection level: signature
+ -->
+ <permission
+ android:name="android.permission.MANAGE_SCOPED_ACCESS_DIRECTORY_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide
+ Allows an application to change the status of a persistable URI permission granted
+ to another application.
+ <p>This permission should <em>only</em> be requested by the platform
+ settings app. This permission cannot be granted to third-party apps.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.FORCE_PERSISTABLE_URI_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- Old permission for deleting an app's cache files, no longer used,
+ but signals for us to quietly ignore calls instead of throwing an exception.
+ <p>Protection level: signature|privileged -->
+ <permission android:name="android.permission.DELETE_CACHE_FILES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to delete cache files.
+ @hide -->
+ <permission android:name="android.permission.INTERNAL_DELETE_CACHE_FILES"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to delete packages.
+ <p>Not for use by third-party applications.
+ <p>Starting in {@link android.os.Build.VERSION_CODES#N}, user confirmation is requested
+ when the application deleting the package is not the same application that installed the
+ package. -->
+ <permission android:name="android.permission.DELETE_PACKAGES"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to move location of installed package.
+ @hide -->
+ <permission android:name="android.permission.MOVE_PACKAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @TestApi Allows an application to keep uninstalled packages as apks.
+ @hide -->
+ <permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to change whether an application component (other than its own) is
+ enabled or not.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to grant specific permissions.
+ @hide -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- @SystemApi Allows an application to launch the settings page which manages various
+ permissions.
+ @hide -->
+ <permission android:name="android.permission.LAUNCH_PERMISSION_SETTINGS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an app that has this permission and the permissions to install packages
+ to request certain runtime permissions to be granted at installation.
+ @hide -->
+ <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- @SystemApi Allows an application to revoke specific permissions.
+ @hide -->
+ <permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature|installer|verifier" />
+
+ <!-- @TestApi Allows an application to revoke the POST_NOTIFICATIONS permission from an app
+ without killing the app. Only granted to the shell.
+ @hide -->
+ <permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows the system to read runtime permission state.
+ @hide -->
+ <permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows the system to restore runtime permission state. This might grant
+ permissions, hence this is a more scoped, less powerful variant of GRANT_RUNTIME_PERMISSIONS.
+ Among other restrictions this cannot override user choices.
+ @hide -->
+ <permission android:name="android.permission.RESTORE_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to change policy_fixed permissions.
+ @hide -->
+ <permission android:name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @SystemApi @TestApi Allows an application to upgrade runtime permissions.
+ @hide -->
+ <permission android:name="android.permission.UPGRADE_RUNTIME_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to allowlist restricted permissions
+ on any of the whitelists.
+ @hide -->
+ <permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @SystemApi Allows an application to an exempt an app from having its permission be
+ auto-revoked when unused for an extended period of time.
+ @hide -->
+ <permission android:name="android.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide Allows an application to observe permission changes. -->
+ <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to start and stop one time permission sessions
+ @hide -->
+ <permission android:name="android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @SystemApi Allows an application to manage the holders of a role.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @SystemApi Allows an application to manage the holders of roles associated with default
+ applications.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_DEFAULT_APPLICATIONS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to bypass role qualification. This allows switching role
+ holders to otherwise non eligible holders. Only the shell is allowed to do this, the
+ qualification for the shell role itself cannot be bypassed, and each role needs to
+ explicitly allow bypassing qualification in its definition. The bypass state will not be
+ persisted across reboot.
+ @hide -->
+ <permission android:name="android.permission.BYPASS_ROLE_QUALIFICATION"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Allows an application to observe role holder changes.
+ @hide -->
+ <permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"
+ android:protectionLevel="signature|installer" />
+
+ <!-- Allows an application to manage the companion devices.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
+ android:protectionLevel="signature|role|module" />
+
+ <!-- Allows an application to subscribe to notifications about the presence status change
+ of their associated companion device
+ -->
+ <permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to deliver companion messages to system
+ -->
+ <permission android:name="android.permission.DELIVER_COMPANION_MESSAGES"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi Allows an application to send and receive messages via CDM transports.
+ @hide -->
+ <permission android:name="android.permission.USE_COMPANION_TRANSPORTS"
+ android:protectionLevel="signature|module" />
+
+ <!-- Allows an application to create new companion device associations.
+ @SystemApi
+ @hide -->
+ <permission android:name="android.permission.ASSOCIATE_COMPANION_DEVICES"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_SURFACE_FLINGER"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to rotate a surface by arbitrary degree.
+ This is a sub-feature of ACCESS_SURFACE_FLINGER and can be granted in a more concrete way.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.ROTATE_SURFACE_FLINGER"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @SystemApi Allows an application to provide hints to SurfaceFlinger that can influence
+ its wakes up time to compose the next frame. This is a subset of the capabilities granted
+ by {@link #ACCESS_SURFACE_FLINGER}.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.WAKEUP_SURFACE_FLINGER"
+ android:protectionLevel="signature|recents" />
+
+ <!-- Allows an application to take screen shots and more generally
+ get access to the frame buffer data.
+ <p>Not for use by third-party applications.
+ @hide
+ @removed -->
+ <permission android:name="android.permission.READ_FRAME_BUFFER"
+ android:protectionLevel="signature|recents" />
+
+ <!-- Allows an application to use InputFlinger's low level features.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_INPUT_FLINGER"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to disable/enable input devices.
+ Could be used to prevent unwanted touch events
+ on a touchscreen, for example during swimming or rain.
+ @hide -->
+ <permission android:name="android.permission.DISABLE_INPUT_DEVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to configure and connect to Wifi displays
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY"
+ android:protectionLevel="signature|knownSigner"
+ android:knownCerts="@array/wifi_known_signers" />
+
+ <!-- Allows an application to control low-level features of Wifi displays
+ such as opening an RTSP socket. This permission should only be used
+ by the display manager.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_WIFI_DISPLAY"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to control the color modes set for displays system-wide.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CONFIGURE_DISPLAY_COLOR_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to control the lights on the device.
+ @hide
+ @SystemApi
+ @TestApi -->
+ <permission android:name="android.permission.CONTROL_DEVICE_LIGHTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to control the color saturation of the display.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.CONTROL_DISPLAY_SATURATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to control display color transformations.
+ <p>Not for use by third-party applications.</p>
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to collect usage infomation about brightness slider changes.
+ <p>Not for use by third-party applications.</p>
+ @hide
+ @SystemApi
+ @TestApi -->
+ <permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to collect ambient light stats.
+ <p>Not for use by third party applications.</p>
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.ACCESS_AMBIENT_LIGHT_STATS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to modify the display brightness configuration
+ @hide
+ @SystemApi
+ @TestApi -->
+ <permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows an application to control the system's display brightness
+ @hide -->
+ <permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to override the display mode requests
+ so the app requested mode will be selected and user settings and display
+ policies will be ignored.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to modify the refresh rate switching type. This
+ matches Setting.Secure.MATCH_CONTENT_FRAME_RATE.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to modify the user preferred display mode.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to modify the HDR conversion mode.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.MODIFY_HDR_CONVERSION_MODE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to control VPN.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CONTROL_VPN"
+ android:protectionLevel="signature|privileged" />
+ <uses-permission android:name="android.permission.CONTROL_VPN" />
+
+ <!-- Allows an application to access and modify always-on VPN configuration.
+ <p>Not for use by third-party or privileged applications.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to capture the audio from tuner input devices types,
+ such as FM_TUNER.
+
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CAPTURE_TUNER_AUDIO_INPUT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to capture audio output.
+ Use the {@code CAPTURE_MEDIA_OUTPUT} permission if only the {@code USAGE_UNKNOWN}),
+ {@code USAGE_MEDIA}) or {@code USAGE_GAME}) usages are intended to be captured.
+ <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to capture the audio played by other apps
+ that have set an allow capture policy of
+ {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM}.
+
+ Without this permission, only audio with an allow capture policy of
+ {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_ALL} can be used.
+
+ There are strong restriction listed at
+ {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM}
+ on what an app can do with the captured audio.
+
+ See {@code CAPTURE_AUDIO_OUTPUT} for capturing audio use cases other than media playback.
+
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CAPTURE_MEDIA_OUTPUT"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to capture the audio played by other apps
+ with the {@code USAGE_VOICE_COMMUNICATION} usage.
+
+ The application may opt out of capturing by setting an allow capture policy of
+ {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
+
+ There are strong restriction listed at
+ {@link android.media.AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM}
+ on what an app can do with the captured audio.
+
+ See {@code CAPTURE_AUDIO_OUTPUT} and {@code CAPTURE_MEDIA_OUTPUT} for capturing
+ audio use cases other than voice communication playback.
+
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to capture audio for hotword detection.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to access the ultrasound content.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.ACCESS_ULTRASOUND"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Puts an application in the chain of trust for sound trigger
+ operations. Being in the chain of trust allows an application to
+ delegate an identity of a separate entity to the sound trigger system
+ and vouch for the authenticity of this identity.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.SOUNDTRIGGER_DELEGATE_IDENTITY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to modify audio routing and override policy decisions.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to access the uplink and downlink audio of an ongoing
+ call.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CALL_AUDIO_INTERCEPTION"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!--@SystemApi Allows an application to modify system audio settings that shouldn't be
+ controllable by external apps, such as volume settings or volume behaviors for audio
+ devices, regardless of their connection status.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @TestApi Allows an application to query audio related state.
+ @hide -->
+ <permission android:name="android.permission.QUERY_AUDIO_STATE"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows an application to modify what effects are applied to all audio
+ (matching certain criteria) from any application.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to disable system sound effects when the user exits one of
+ the application's activities.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.DISABLE_SYSTEM_SOUND_EFFECTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to provide remote displays.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.REMOTE_DISPLAY_PROVIDER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to capture video output.
+ <p>Not for use by third-party applications.</p>
+ @hide
+ @removed -->
+ <permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to capture secure video output.
+ <p>Not for use by third-party applications.</p>
+ @hide
+ @removed -->
+ <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to know what content is playing and control its playback.
+ <p>Not for use by third-party applications due to privacy of media consumption</p> -->
+ <permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to set the volume key long-press listener.
+ <p>When it's set, the application will receive the volume key long-press event
+ instead of changing volume.</p>
+ <p>Not for use by third-party applications</p> -->
+ <permission android:name="android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @SystemApi @hide Allows an application to set media key event listener.
+ <p>When it's set, the application will receive the media key event before
+ any other media sessions. If the event is handled by the listener, other sessions
+ cannot get the event.</p>
+ <p>Not for use by third-party applications</p> -->
+ <permission android:name="android.permission.SET_MEDIA_KEY_LISTENER"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @SystemApi Required to be able to disable the device (very dangerous!).
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.BRICK"
+ android:protectionLevel="signature" />
+
+ <!-- Required to be able to reboot the device.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.REBOOT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows low-level access to power management.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.DEVICE_POWER"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows toggling battery saver on the system.
+ Superseded by DEVICE_POWER permission. @hide @SystemApi
+ -->
+ <permission android:name="android.permission.POWER_SAVER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows providing the system with battery predictions.
+ Superseded by DEVICE_POWER permission. @hide @SystemApi
+ -->
+ <permission android:name="android.permission.BATTERY_PREDICTION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows access to the PowerManager.userActivity function.
+ <p>Not for use by third-party applications. @hide @SystemApi -->
+ <permission android:name="android.permission.USER_ACTIVITY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @SystemApi Allows an application to manage Low Power Standby settings.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_LOW_POWER_STANDBY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @SystemApi Allows an application to request ports to remain open during
+ Low Power Standby.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SET_LOW_POWER_STANDBY_PORTS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows low-level access to tun tap driver -->
+ <permission android:name="android.permission.NET_TUNNELING"
+ android:protectionLevel="signature|role" />
+
+ <!-- Run as a manufacturer test application, running as the root user.
+ Only available when the device is running in manufacturer test mode.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.FACTORY_TEST"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @TestApi @SystemApi Allows an application to broadcast the intent {@link
+ android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS}.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"
+ android:protectionLevel="signature|privileged|recents" />
+ <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
+
+ <!-- Allows an application to broadcast a notification that an application
+ package has been removed.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.BROADCAST_PACKAGE_REMOVED"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to broadcast an SMS receipt notification.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.BROADCAST_SMS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to broadcast a WAP PUSH receipt notification.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.BROADCAST_WAP_PUSH"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to broadcast privileged networking requests.
+ <p>Not for use by third-party applications.
+ @hide
+ @deprecated Use {@link android.Manifest.permission#REQUEST_NETWORK_SCORES} instead
+ -->
+ <permission android:name="android.permission.BROADCAST_NETWORK_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Not for use by third-party applications. -->
+ <permission android:name="android.permission.MASTER_CLEAR"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an application to call any phone number, including emergency
+ numbers, without going through the Dialer user interface for the user
+ to confirm the call being placed.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CALL_PRIVILEGED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to perform CDMA OTA provisioning @hide -->
+ <permission android:name="android.permission.PERFORM_CDMA_PROVISIONING"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to perform SIM Activation @hide -->
+ <permission android:name="android.permission.PERFORM_SIM_ACTIVATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows enabling/disabling location update notifications from
+ the radio.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CONTROL_LOCATION_UPDATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows read/write access to the "properties" table in the checkin
+ database, to change values that get uploaded.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.ACCESS_CHECKIN_PROPERTIES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to collect component usage
+ statistics
+ <p>Declaring the permission implies intention to use the API and the user of the
+ device can grant permission through the Settings application.
+ <p>Protection level: signature|privileged|development|appop|retailDemo -->
+ <permission android:name="android.permission.PACKAGE_USAGE_STATS"
+ android:protectionLevel="signature|privileged|development|appop|retailDemo" />
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+
+ <!-- @SystemApi @hide Allows trusted system components to report events to UsageStatsManager -->
+ <permission android:name="android.permission.REPORT_USAGE_STATS"
+ android:protectionLevel="signature|module" />
+
+ <!-- Allows an application to query broadcast response stats (see
+ {@link android.app.usage.BroadcastResponseStats}).
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_BROADCAST_RESPONSE_STATS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- Allows a data loader to read a package's access logs. The access logs contain the
+ set of pages referenced over time.
+ <p>Declaring the permission implies intention to use the API and the user of the
+ device can grant permission through the Settings application.
+ <p>Protection level: signature|privileged|appop
+ <p>A data loader has to be the one which provides data to install an app.
+ <p>A data loader has to have both permission:LOADER_USAGE_STATS AND
+ appop:LOADER_USAGE_STATS allowed to be able to access the read logs. -->
+ <permission android:name="android.permission.LOADER_USAGE_STATS"
+ android:protectionLevel="signature|privileged|appop" />
+ <uses-permission android:name="android.permission.LOADER_USAGE_STATS" />
+
+ <!-- @hide @SystemApi Allows an application to observe usage time of apps. The app can register
+ for callbacks when apps reach a certain usage time limit, etc. -->
+ <permission android:name="android.permission.OBSERVE_APP_USAGE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @hide @TestApi @SystemApi Allows an application to change the app idle state of an app.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @TestApi @SystemApi Allows an application to change the estimated launch time
+ of an app.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @SystemApi Allows an application to temporarily allowlist an inactive app to
+ access the network and acquire wakelocks.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Permission an application must hold in order to use
+ {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
+ <p>Protection level: normal -->
+ <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
+ android:label="@string/permlab_requestIgnoreBatteryOptimizations"
+ android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
+ android:protectionLevel="normal" />
+
+ <!-- Allows an application to collect battery statistics
+ <p>Protection level: signature|privileged|development -->
+ <permission android:name="android.permission.BATTERY_STATS"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!--Allows an application to manage statscompanion.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.STATSCOMPANION"
+ android:protectionLevel="signature" />
+
+ <!--@SystemApi @hide Allows an application to register stats pull atom callbacks.
+ <p>Not for use by third-party applications.-->
+ <permission android:name="android.permission.REGISTER_STATS_PULL_ATOM"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to read restricted stats from statsd.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_RESTRICTED_STATS"
+ android:protectionLevel="internal|privileged" />
+
+ <!-- @SystemApi Allows an application to control the backup and restore process.
+ <p>Not for use by third-party applications.
+ @hide pending API council -->
+ <permission android:name="android.permission.BACKUP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to make modifications to device settings such that these
+ modifications will be overridden by settings restore..
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE"
+ android:protectionLevel="signature|setup" />
+
+ <!-- @SystemApi Allows application to manage
+ {@link android.security.keystore.recovery.RecoveryController}.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.RECOVER_KEYSTORE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows application to verify lockscreen credentials provided by a remote device.
+ @hide -->
+ <permission android:name="android.permission.CHECK_REMOTE_LOCKSCREEN"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows a package to launch the secure full-backup confirmation UI.
+ ONLY the system process may hold this permission.
+ @hide -->
+ <permission android:name="android.permission.CONFIRM_FULL_BACKUP"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link android.widget.RemoteViewsService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged -->
+ <permission android:name="android.permission.BIND_REMOTEVIEWS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to tell the AppWidget service which application
+ can access AppWidget's data. The normal user flow is that a user
+ picks an AppWidget to go into a particular host, thereby giving that
+ host application access to the private data from the AppWidget app.
+ An application that has this permission should honor that contract.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.BIND_APPWIDGET"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows sysui to manage user grants of slice permissions. -->
+ <permission android:name="android.permission.MANAGE_SLICE_PERMISSIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Private permission, to restrict who can bring up a dialog to add a new
+ keyguard widget
+ @hide -->
+ <permission android:name="android.permission.BIND_KEYGUARD_APPWIDGET"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Internal permission allowing an application to query/set which
+ applications can bind AppWidgets.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows applications to change the background data setting.
+ <p>Not for use by third-party applications.
+ @hide pending API council -->
+ <permission android:name="android.permission.CHANGE_BACKGROUND_DATA_SETTING"
+ android:protectionLevel="signature" />
+
+ <!-- This permission can be used on content providers to allow the global
+ search system to access their data. Typically it used when the
+ provider has some permissions protecting it (which global search
+ would not be expected to hold), and added as a read-only permission
+ to the path in the provider where global search queries are
+ performed. This permission can not be held by regular applications;
+ it is used by applications to protect themselves from everyone else
+ besides global search.
+ <p>Protection level: signature|privileged -->
+ <permission android:name="android.permission.GLOBAL_SEARCH"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Internal permission protecting access to the global search
+ system: ensures that only the system can access the provider
+ to perform queries (since this otherwise provides unrestricted
+ access to a variety of content providers), and to write the
+ search statistics (to keep applications from gaming the source
+ ranking).
+ @hide -->
+ <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Internal permission to allows an application to read indexable data.
+ @hide -->
+ <permission android:name="android.permission.READ_SEARCH_INDEXABLES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Internal permission to allows an application to bind to suggestion service.
+ @hide -->
+ <permission android:name="android.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Internal permission to allows an application to access card content provider. -->
+ <permission android:name="android.permission.WRITE_SETTINGS_HOMEPAGE_DATA"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- An application needs this permission for
+ {@link android.provider.Settings#ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY} to show its
+ {@link android.app.Activity} embedded in Settings app. -->
+ <permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- @SystemApi {@link android.app.Activity} should require this permission to ensure that only
+ the settings app can embed it in a multi pane window.
+ @hide -->
+ <permission android:name="android.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows applications to set a live wallpaper.
+ @hide XXX Change to signature once the picker is moved to its
+ own apk as Ghod Intended. -->
+ <permission android:name="android.permission.SET_WALLPAPER_COMPONENT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows applications to set wallpaper dim amount.
+ @hide -->
+ <permission android:name="android.permission.SET_WALLPAPER_DIM_AMOUNT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows applications to read dream settings and dream state.
+ @hide -->
+ <permission android:name="android.permission.READ_DREAM_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows applications to write dream settings, and start or stop dreaming.
+ @hide -->
+ <permission android:name="android.permission.WRITE_DREAM_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows applications to read whether ambient display is suppressed. -->
+ <permission android:name="android.permission.READ_DREAM_SUPPRESSION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allow an application to read and write the cache partition.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by default container service so that only
+ the system can bind to it and use it to copy
+ protected data to secure containers or files
+ accessible to the system.
+ @hide -->
+ <permission android:name="android.permission.COPY_PROTECTED_DATA"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Internal permission protecting access to the encryption methods
+ @hide
+ -->
+ <permission android:name="android.permission.CRYPT_KEEPER"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to read historical network usage for
+ specific networks and applications. @hide -->
+ <permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to manage network policies (such as warning and disable
+ limits) and to define application-specific rules. @hide -->
+ <permission android:name="android.permission.MANAGE_NETWORK_POLICY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide @deprecated use UPDATE_DEVICE_STATS instead -->
+ <permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi @hide Allows an application to manage carrier subscription plans. -->
+ <permission android:name="android.permission.MANAGE_SUBSCRIPTION_PLANS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- C2DM permission.
+ @hide Used internally.
+ -->
+ <permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
+
+ <!-- @SystemApi @hide Package verifier needs to have this permission before the PackageManager will
+ trust it to verify packages.
+ -->
+ <permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by package verifier receiver, to ensure that only the
+ system can interact with it.
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Rollback manager needs to have this permission before the PackageManager will
+ trust it to enable rollback.
+ -->
+ <permission android:name="android.permission.PACKAGE_ROLLBACK_AGENT"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @TestApi @hide Allows managing apk level rollbacks. -->
+ <permission android:name="android.permission.MANAGE_ROLLBACKS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @TestApi @hide Allows testing apk level rollbacks. -->
+ <permission android:name="android.permission.TEST_MANAGE_ROLLBACKS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an application to mark other applications as harmful -->
+ <permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS"
+ android:protectionLevel="signature|verifier" />
+
+ <!-- @SystemApi @hide Intent filter verifier needs to have this permission before the
+ PackageManager will trust it to verify intent filters.
+ -->
+ <permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by intent filter verifier rintent-filtereceiver, to ensure that only the
+ system can interact with it.
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_INTENT_FILTER_VERIFIER"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Domain verification agent package needs to have this permission before the
+ system will trust it to verify domains.
+
+ TODO(159952358): STOPSHIP: This must be updated to the new "internal" protectionLevel
+ -->
+ <permission android:name="android.permission.DOMAIN_VERIFICATION_AGENT"
+ android:protectionLevel="internal|privileged" />
+
+ <!-- @SystemApi @hide Must be required by the domain verification agent's intent
+ BroadcastReceiver, to ensure that only the system can interact with it.
+ -->
+ <permission android:name="android.permission.BIND_DOMAIN_VERIFICATION_AGENT"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @hide Allows an app like Settings to update the user's grants to what domains
+ an app is allowed to automatically open.
+ -->
+ <permission android:name="android.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows applications to access serial ports via the SerialManager.
+ @hide -->
+ <permission android:name="android.permission.SERIAL_PORT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows the holder to access content providers from outside an ApplicationThread.
+ This permission is enforced by the ActivityManagerService on the corresponding APIs,
+ in particular ActivityManagerService#getContentProviderExternal(String) and
+ ActivityManagerService#removeContentProviderExternal(String).
+ @hide
+ -->
+ <permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to hold an UpdateLock, recommending that a headless
+ OTA reboot *not* occur while the lock is held.
+ @hide -->
+ <permission android:name="android.permission.UPDATE_LOCK"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application the opportunity to become a
+ {@link android.service.notification.NotificationAssistantService}.
+ User permission is still required before access is granted.
+ @hide -->
+ <permission android:name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi @TestApi Allows an application to read the current set of notifications, including
+ any metadata and intents attached.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_NOTIFICATIONS"
+ android:protectionLevel="signature|privileged|appop" />
+
+ <!-- Marker permission for applications that wish to access notification policy. This permission
+ is not supported on managed profiles.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"
+ android:description="@string/permdesc_access_notification_policy"
+ android:label="@string/permlab_access_notification_policy"
+ android:protectionLevel="normal" />
+
+ <!-- Allows modification of do not disturb rules and policies. Only allowed for system
+ processes.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_NOTIFICATIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi @TestApi Allows adding/removing enabled notification listener components.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS"
+ android:protectionLevel="signature|installer" />
+ <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" />
+
+ <!-- @SystemApi Allows notifications to be colorized
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.USE_COLORIZED_NOTIFICATIONS"
+ android:protectionLevel="signature|setup|role" />
+
+ <!-- Allows access to keyguard secure storage. Only allowed for system processes.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
+ android:protectionLevel="signature|setup" />
+
+ <!-- Allows applications to set the initial lockscreen state.
+ <p>Not for use by third-party applications. @hide -->
+ <permission android:name="android.permission.SET_INITIAL_LOCK"
+ android:protectionLevel="signature|setup"/>
+
+ <!-- @TestApi Allows applications to set and verify lockscreen credentials.
+ @hide -->
+ <permission android:name="android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS"
+ android:protectionLevel="signature"/>
+
+ <!-- Allows managing (adding, removing) fingerprint templates. Reserved for the system. @hide -->
+ <permission android:name="android.permission.MANAGE_FINGERPRINT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows managing (adding, removing) face templates. Reserved for the system. @hide -->
+ <permission android:name="android.permission.MANAGE_FACE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an app to reset fingerprint attempt counter. Reserved for the system. @hide -->
+ <permission android:name="android.permission.RESET_FINGERPRINT_LOCKOUT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows access to TestApis for various components in the biometric stack, including
+ FingerprintService, FaceService, BiometricService. Used by com.android.server.biometrics
+ CTS tests. @hide @TestApi -->
+ <permission android:name="android.permission.TEST_BIOMETRIC"
+ android:protectionLevel="signature" />
+
+ <!-- Allows direct access to the <Biometric>Service interfaces. Reserved for the system. @hide -->
+ <permission android:name="android.permission.MANAGE_BIOMETRIC"
+ android:protectionLevel="signature" />
+
+ <!-- Allows direct access to the <Biometric>Service authentication methods. Reserved for the system. @hide -->
+ <permission android:name="android.permission.USE_BIOMETRIC_INTERNAL"
+ android:protectionLevel="signature" />
+
+ <!-- Allows the system to control the BiometricDialog (SystemUI). Reserved for the system. @hide -->
+ <permission android:name="android.permission.MANAGE_BIOMETRIC_DIALOG"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to control keyguard. Only allowed for system processes.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_KEYGUARD"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to control keyguard features like secure notifications.
+ @hide -->
+ <permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to manage weak escrow token on the device. This permission
+ is not available to third party applications.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_WEAK_ESCROW_TOKEN"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to listen to trust changes. Only allowed for system processes.
+ @hide -->
+ <permission android:name="android.permission.TRUST_LISTENER"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to provide a trust agent.
+ @hide For security reasons, this is a platform-only permission. -->
+ <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to show a message
+ on the keyguard when asking to dismiss it.
+ @hide For security reasons, this is a platform-only permission. -->
+ <permission android:name="android.permission.SHOW_KEYGUARD_MESSAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to launch the trust agent settings activity.
+ @hide -->
+ <permission android:name="android.permission.LAUNCH_TRUST_AGENT_SETTINGS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Must be required by an {@link
+ android.service.trust.TrustAgentService},
+ to ensure that only the system can bind to it.
+ @hide -->
+ <permission android:name="android.permission.BIND_TRUST_AGENT"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link
+ android.service.notification.NotificationListenerService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be required by an {@link
+ android.service.notification.NotificationAssistantService} to ensure that only the system
+ can bind to it.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link
+ android.service.chooser.ChooserTargetService}, to ensure that
+ only the system can bind to it.
+ <p>Protection level: signature
+
+ @deprecated For publishing direct share targets, please follow the instructions in
+ https://developer.android.com/training/sharing/receive.html#providing-direct-share-targets
+ instead.
+ -->
+ <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Must be held by services that extend
+ {@link android.service.resolver.ResolverRankerService}.
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Must be required by services that extend
+ {@link android.service.resolver.ResolverRankerService}, to ensure that only the system can
+ bind to them.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by a {@link
+ android.service.notification.ConditionProviderService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.service.dreams.DreamService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_DREAM_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.app.usage.CacheQuotaService} to ensure that only the
+ system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_CACHE_QUOTA_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to call into a carrier setup flow. It is up to the
+ carrier setup application to enforce that this permission is required
+ @hide This is not a third-party API (intended for OEMs and system apps). -->
+ <permission android:name="android.permission.INVOKE_CARRIER_SETUP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to listen for network condition observations.
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.ACCESS_NETWORK_CONDITIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to provision and access DRM certificates
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.ACCESS_DRM_CERTIFICATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Api Allows an application to manage media projection sessions.
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.MANAGE_MEDIA_PROJECTION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to read install sessions
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.READ_INSTALL_SESSIONS"
+ android:label="@string/permlab_readInstallSessions"
+ android:description="@string/permdesc_readInstallSessions"
+ android:protectionLevel="normal"/>
+
+ <!-- @SystemApi Allows an application to remove DRM certificates
+ @hide This is not a third-party API (intended for system apps). -->
+ <permission android:name="android.permission.REMOVE_DRM_CERTIFICATES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @deprecated Use {@link android.Manifest.permission#BIND_CARRIER_SERVICES} instead -->
+ <permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to interact with the currently active
+ {@link android.service.voice.VoiceInteractionService}.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- The system process that is allowed to bind to services in carrier apps will
+ have this permission. Carrier apps should use this permission to protect
+ their services that only the system is allowed to bind to.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_CARRIER_SERVICES"
+ android:label="@string/permlab_bindCarrierServices"
+ android:description="@string/permdesc_bindCarrierServices"
+ android:protectionLevel="signature|privileged" />
+
+ <!--
+ Allows the holder to start the permission usage screen for an app.
+ <p>Protection level: signature|installer
+ -->
+ <permission android:name="android.permission.START_VIEW_PERMISSION_USAGE"
+ android:label="@string/permlab_startViewPermissionUsage"
+ android:description="@string/permdesc_startViewPermissionUsage"
+ android:protectionLevel="signature|installer|module" />
+
+ <!--
+ @SystemApi
+ Allows the holder to start the screen to review permission decisions.
+ <p>Protection level: signature|installer
+ @hide -->
+ <permission android:name="android.permission.START_REVIEW_PERMISSION_DECISIONS"
+ android:label="@string/permlab_startReviewPermissionDecisions"
+ android:description="@string/permdesc_startReviewPermissionDecisions"
+ android:protectionLevel="signature|installer" />
+
+ <!--
+ Allows the holder to start the screen with a list of app features.
+ <p>Protection level: signature|installer
+ -->
+ <permission android:name="android.permission.START_VIEW_APP_FEATURES"
+ android:label="@string/permlab_startViewAppFeatures"
+ android:description="@string/permdesc_startViewAppFeatures"
+ android:protectionLevel="signature|installer" />
+
+ <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
+ flag is set.
+ @hide -->
+ <permission android:name="android.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows applications to kill UIDs.
+ <p>This permission can be granted to the SYSTEM_SUPERVISOR role used for parental
+ controls.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.KILL_UID"
+ android:protectionLevel="signature|installer|role" />
+
+ <!-- @SystemApi Allows applications to read the local WiFi and Bluetooth MAC address.
+ @hide -->
+ <permission android:name="android.permission.LOCAL_MAC_ADDRESS"
+ android:protectionLevel="signature|privileged" />
+ <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS"/>
+
+ <!-- @SystemApi Allows access to MAC addresses of WiFi and Bluetooth peer devices.
+ @hide -->
+ <permission android:name="android.permission.PEERS_MAC_ADDRESS"
+ android:protectionLevel="signature|setup|role" />
+
+ <!-- Allows the Nfc stack to dispatch Nfc messages to applications. Applications
+ can use this permission to ensure incoming Nfc messages are from the Nfc stack
+ and not simulated by another application.
+ @hide -->
+ <permission android:name="android.permission.DISPATCH_NFC_MESSAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows changing day / night mode when system is configured with
+ config_lockDayNightMode set to true. If requesting app does not have permission,
+ it will be ignored.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows entering or exiting car mode using a specified priority.
+ This permission is required to use UiModeManager while specifying a priority for the calling
+ app. A device manufacturer uses this permission to prioritize the apps which can
+ potentially request to enter car-mode on a device to help establish the correct behavior
+ where multiple such apps are active at the same time.
+ @hide -->
+ <permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Required to receive ACTION_ENTER_CAR_MODE_PRIVILEGED or
+ ACTION_EXIT_CAR_MODE_PRIVILEGED.
+ @hide -->
+ <permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows the holder to send category_car notifications.
+ @hide -->
+ <permission
+ android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- The system process is explicitly the only one allowed to launch the
+ confirmation UI for full backup/restore -->
+ <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
+
+ <!-- @SystemApi Allows the holder to access and manage instant applications on the device.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_INSTANT_APPS"
+ android:protectionLevel="signature|installer|verifier|role" />
+ <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS"/>
+
+ <!-- Allows the holder to view the instant applications on the device.
+ @hide -->
+ <permission android:name="android.permission.VIEW_INSTANT_APPS"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- Allows the holder to manage whether the system can bind to services
+ provided by instant apps. This permission is intended to protect
+ test/development fucntionality and should be used only in such cases.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Allows receiving the usage of media resource e.g. video/audio codec and
+ graphic memory.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by system/priv apps when accessing the sound trigger
+ APIs given by {@link SoundTriggerManager}.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Must be required by system/priv apps to run sound trigger recognition sessions while in
+ battery saver mode.
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Must be required by system/priv apps implementing sound trigger detection services
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows trusted applications to dispatch managed provisioning message to Managed
+ Provisioning app. If requesting app does not have permission, it will be ignored.
+ @hide -->
+ <permission android:name="android.permission.DISPATCH_PROVISIONING_MESSAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows the holder to read blocked numbers. See
+ {@link android.provider.BlockedNumberContract}.
+ @hide -->
+ <permission android:name="android.permission.READ_BLOCKED_NUMBERS"
+ android:protectionLevel="signature" />
+
+ <!-- Allows the holder to write blocked numbers. See
+ {@link android.provider.BlockedNumberContract}.
+ @hide -->
+ <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
+ the system can bind to it.
+ <p>Protection level: signature -->
+ <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by system apps when accessing restricted VR APIs.
+ @hide
+ @SystemApi
+ <p>Protection level: signature -->
+ <permission android:name="android.permission.RESTRICTED_VR_ACCESS"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- Required to make calls to {@link android.service.vr.IVrManager}.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_VR_MANAGER"
+ android:protectionLevel="signature" />
+
+ <!-- Required to access VR-Mode state and state change events via {android.app.VrStateCallback}
+ @hide -->
+ <permission android:name="android.permission.ACCESS_VR_STATE"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- Allows an application to allowlist tasks during lock task mode
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.UPDATE_LOCK_TASK_PACKAGES"
+ android:protectionLevel="signature|setup" />
+
+ <!-- @SystemApi Allows an application to replace the app name displayed alongside notifications
+ in the N-release and later.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to show notifications before the device is provisioned.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.NOTIFICATION_DURING_SETUP"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to manage auto-fill sessions.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_AUTO_FILL"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to manage the content capture service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_CONTENT_CAPTURE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to manager the rotation resolver service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_ROTATION_RESOLVER"
+ android:protectionLevel="signature"/>
+
+ <!-- @SystemApi Allows an application to manage the music recognition service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_MUSIC_RECOGNITION"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- @SystemApi Allows an application to manage speech recognition service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_SPEECH_RECOGNITION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to manage the content suggestions service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to manage the app predictions service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_APP_PREDICTIONS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to manage the search ui service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_SEARCH_UI"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to manage the smartspace service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_SMARTSPACE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to access the smartspace service as a client.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.ACCESS_SMARTSPACE"
+ android:protectionLevel="signature|privileged|development" />
+
+ <!-- @SystemApi Allows an application to manage the wallpaper effects
+ generation service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to manage the cloudsearch service.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MANAGE_CLOUDSEARCH"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an app to set the theme overlay in /vendor/overlay
+ being used.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.MODIFY_THEME_OVERLAY"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an instant app to create foreground services.
+ <p>Protection level: signature|development|instant|appop -->
+ <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
+ android:protectionLevel="signature|development|instant|appop" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground}.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE"
+ android:description="@string/permdesc_foregroundService"
+ android:label="@string/permlab_foregroundService"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "camera".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "connectedDevice".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "dataSync".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "location".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "mediaPlayback".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "mediaProjection".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "microphone".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "phoneCall".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "health".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "remoteMessaging".
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "systemExempted".
+ Apps are allowed to use this type only in the use cases listed in
+ {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED}.
+ <p>Protection level: normal|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "fileManagement".
+ <p>Protection level: normal|instant
+ @hide
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_FILE_MANAGEMENT"
+ android:description="@string/permdesc_foregroundServiceFileManagement"
+ android:label="@string/permlab_foregroundServiceFileManagement"
+ android:protectionLevel="normal|instant" />
+
+ <!-- Allows a regular application to use {@link android.app.Service#startForeground
+ Service.startForeground} with the type "specialUse".
+ <p>Protection level: normal|appop|instant
+ -->
+ <permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
+ android:protectionLevel="normal|appop|instant" />
+
+ <!-- @SystemApi Allows to access all app shortcuts.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_SHORTCUTS"
+ android:protectionLevel="signature|role|recents" />
+
+ <!-- @SystemApi Allows unlimited calls to shortcut mutation APIs.
+ @hide -->
+ <permission android:name="android.permission.UNLIMITED_SHORTCUTS_API_CALLS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to read the runtime profiles of other apps.
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_RUNTIME_PROFILES"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide Allows audio policy management. -->
+ <permission android:name="android.permission.MANAGE_AUDIO_POLICY"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to turn on / off quiet mode.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_QUIET_MODE"
+ android:protectionLevel="signature|privileged|development|role" />
+
+ <!-- Allows internal management of the camera framework
+ @hide -->
+ <permission android:name="android.permission.MANAGE_CAMERA"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an application to control remote animations. See
+ {@link ActivityOptions#makeRemoteAnimation}
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to watch changes and/or active state of app ops.
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.WATCH_APPOPS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows hidden API checks to be disabled when starting a process.
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Permission that protects the
+ {@link android.provider.Telephony.Intents#ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
+ broadcast -->
+ <permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- A subclass of {@link android.service.carrier.CarrierMessagingClientService} must be protected with this permission.
+ <p>Protection level: signature -->
+ <permission android:name="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- Must be required by an {@link android.service.watchdog.ExplicitHealthCheckService} to
+ ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Must be required by an {@link android.service.storage.ExternalStorageService} to
+ ensure that only the system can bind to it.
+ @hide This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_EXTERNAL_STORAGE_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Permission that allows configuring appops.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_APPOPS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Permission that allows background clipboard access.
+ @hide Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Permission that allows apps to disable the clipboard access notifications.
+ @hide
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide Permission that suppresses the notification when the clipboard is accessed.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SUPPRESS_CLIPBOARD_ACCESS_NOTIFICATION"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows modifying accessibility state.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_ACCESSIBILITY"
+ android:protectionLevel="signature|setup|recents|role" />
+
+ <!-- @SystemApi Allows an app to grant a profile owner access to device identifiers.
+ <p>Not for use by third-party applications.
+ @deprecated
+ @hide -->
+ <permission android:name="android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an app to mark a profile owner as managing an organization-owned device.
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.MARK_DEVICE_ORGANIZATION_OWNED"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows financial apps to read filtered sms messages.
+ Protection level: signature|appop
+ @deprecated The API that used this permission is no longer functional. -->
+ <permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
+ android:protectionLevel="signature|appop" />
+
+ <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#Q} that want to use
+ {@link android.app.Notification.Builder#setFullScreenIntent notification full screen
+ intents}.
+ <p>Protection level: normal -->
+ <permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
+ android:label="@string/permlab_fullScreenIntent"
+ android:description="@string/permdesc_fullScreenIntent"
+ android:protectionLevel="normal|appop" />
+
+ <!-- @SystemApi Allows requesting the framework broadcast the
+ {@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY} intent.
+ @hide -->
+ <permission android:name="android.permission.SEND_DEVICE_CUSTOMIZATION_READY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Permission that protects the {@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY}
+ intent.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- @SystemApi Allows wallpaper to be rendered in ambient mode.
+ @hide -->
+ <permission android:name="android.permission.AMBIENT_WALLPAPER"
+ android:protectionLevel="signature|preinstalled" />
+
+ <!-- @SystemApi Allows sensor privacy to be modified.
+ @hide -->
+ <permission android:name="android.permission.MANAGE_SENSOR_PRIVACY"
+ android:protectionLevel="internal|role|installer" />
+
+ <!-- @SystemApi Allows sensor privacy changes to be observed.
+ @hide -->
+ <permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY"
+ android:protectionLevel="internal|role|installer" />
+
+ <!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES}
+ intent.
+ @hide -->
+ <permission android:name="android.permission.REVIEW_ACCESSIBILITY_SERVICES"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an activity to replace the app name and icon displayed in share targets
+ in the sharesheet for the Q-release and later.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to access shared libraries.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
+ android:protectionLevel="signature|installer" />
+
+ <!-- Allows an app to log compat change usage.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.LOG_COMPAT_CHANGE"
+ android:protectionLevel="signature|privileged" />
+ <!-- Allows an app to read compat change config.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
+ android:protectionLevel="signature|privileged" />
+ <!-- Allows an app to override compat change config.
+ This permission only allows to override config on debuggable builds or test-apks and is
+ therefore a less powerful version of OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD.
+ @hide <p>Not for use by third-party applications.</p> -->
+ <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
+ android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows an app to override compat change config on release builds.
+ Only ChangeIds that are annotated as @Overridable can be overridden on release builds.
+ @hide -->
+ <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows input events to be monitored. Very dangerous! @hide -->
+ <permission android:name="android.permission.MONITOR_INPUT"
+ android:protectionLevel="signature|recents" />
+ <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
+ window to the window where the touch currently is on top of. @hide -->
+ <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
+ android:protectionLevel="signature|privileged|recents|role" />
+ <!-- Allows the caller to change the associations between input devices and displays.
+ Very dangerous! @hide -->
+ <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
+ android:protectionLevel="signature" />
+
+ <!-- Allows query of any normal app on the device, regardless of manifest declarations.
+ <p>Protection level: normal -->
+ <permission android:name="android.permission.QUERY_ALL_PACKAGES"
+ android:label="@string/permlab_queryAllPackages"
+ android:description="@string/permdesc_queryAllPackages"
+ android:protectionLevel="normal" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+
+ <!-- @hide Allow the caller to collect debugging data from processes that otherwise
+ would require USAGE_STATS. Before sharing this data with other apps, holders
+ of this permission are REQUIRED to themselves check that the caller has
+ PACKAGE_USAGE_STATS and OP_GET_USAGE_STATS. -->
+ <permission android:name="android.permission.PEEK_DROPBOX_DATA"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows an application to access TV tuner HAL
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TV_TUNER"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- @SystemApi Allows an application to access descrambler of TV tuner HAL
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TV_DESCRAMBLER"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- @SystemApi Allows an application to access shared filter of TV tuner HAL
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TV_SHARED_FILTER"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- Allows an application to create trusted displays. @hide @SystemApi -->
+ <permission android:name="android.permission.ADD_TRUSTED_DISPLAY"
+ android:protectionLevel="signature|role" />
+
+ <!-- Allows an application to create always-unlocked displays. @hide @SystemApi -->
+ <permission android:name="android.permission.ADD_ALWAYS_UNLOCKED_DISPLAY"
+ android:protectionLevel="signature|role"/>
+
+ <!-- @hide @SystemApi Allows an application to access locusId events in the usage stats. -->
+ <permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"
+ android:protectionLevel="signature|role" />
+
+ <!-- @hide @SystemApi Allows an application to manage app hibernation state. -->
+ <permission android:name="android.permission.MANAGE_APP_HIBERNATION"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide @TestApi Allows apps to reset the state of {@link com.android.server.am.AppErrors}.
+ <p>CTS tests will use UiAutomation.adoptShellPermissionIdentity() to gain access. -->
+ <permission android:name="android.permission.RESET_APP_ERRORS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to create/destroy input consumer. -->
+ <permission android:name="android.permission.INPUT_CONSUMER"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @TestApi Allows an application to control the system's device state managed by the
+ {@link android.service.devicestate.DeviceStateManagerService}. For example, on foldable
+ devices this would grant access to toggle between the folded and unfolded states. -->
+ <permission android:name="android.permission.CONTROL_DEVICE_STATE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @SystemApi Must be required by a
+ {@link android.service.displayhash.DisplayHashingService}
+ to ensure that only the system can bind to it.
+ This is not a third-party API (intended for OEMs and system apps).
+ -->
+ <permission android:name="android.permission.BIND_DISPLAY_HASHING_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @TestApi Allows an application to enable/disable toast rate limiting.
+ <p>Not for use by third-party applications.
+ -->
+ <permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows managing the Game Mode
+ @hide -->
+ <permission android:name="android.permission.MANAGE_GAME_MODE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows accessing the frame rate per second of a given application
+ @hide -->
+ <permission android:name="android.permission.ACCESS_FPS_COUNTER"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows managing the GameService APIs
+ @hide -->
+ <permission android:name="android.permission.MANAGE_GAME_ACTIVITY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows managing the Game service
+ @hide @TestApi Used only for testing. -->
+ <permission android:name="android.permission.SET_GAME_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows the holder to register callbacks to inform the RebootReadinessManager
+ when they are performing reboot-blocking work.
+ @hide -->
+ <permission android:name="android.permission.SIGNAL_REBOOT_READINESS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows an application to change the touch mode state.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to get a People Tile preview for a given shortcut. -->
+ <permission android:name="android.permission.GET_PEOPLE_TILE_PREVIEW"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @hide @SystemApi Allows an application to retrieve whether shortcut is backed by a
+ Conversation.
+ TODO(b/180412052): STOPSHIP: Define a role so it can be granted to Shell and AiAi. -->
+ <permission android:name="android.permission.READ_PEOPLE_DATA"
+ android:protectionLevel="signature|recents|role"/>
+
+ <!-- @hide @SystemApi Allows a logical component within an application to
+ temporarily renounce a set of otherwise granted permissions. -->
+ <permission android:name="android.permission.RENOUNCE_PERMISSIONS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to read nearby streaming policy. The policy controls
+ whether to allow the device to stream its notifications and apps to nearby devices. -->
+ <permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi Allows the holder to set the source of the data when setting a clip on the
+ clipboard.
+ @hide -->
+ <permission android:name="android.permission.SET_CLIP_SOURCE"
+ android:protectionLevel="signature|recents" />
+
+ <!-- @SystemApi Allows an application to access TV tuned info
+ <p>Not for use by third-party applications.
+ @hide -->
+ <permission android:name="android.permission.ACCESS_TUNED_INFO"
+ android:protectionLevel="signature|privileged|vendorPrivileged" />
+
+ <!-- Allows an application to indicate via
+ {@link android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(int)}
+ that user action should not be required for an app update.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"
+ android:label="@string/permlab_updatePackagesWithoutUserAction"
+ android:description="@string/permdesc_updatePackagesWithoutUserAction"
+ android:protectionLevel="normal" />
+ <uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION"/>
+
+ <!-- Allows an application to indicate via {@link
+ android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership}
+ that it has the intention of becoming the update owner.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.ENFORCE_UPDATE_OWNERSHIP"
+ android:protectionLevel="normal" />
+ <uses-permission android:name="android.permission.ENFORCE_UPDATE_OWNERSHIP" />
+
+ <!-- Allows an application to take screenshots of layers that normally would be blacked out when
+ a screenshot is taken. Specifically, layers that have the flag
+ {@link android.view.SurfaceControl#SECURE} will be screenshot if the caller requests to
+ capture secure layers. Normally those layers will be rendered black.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.CAPTURE_BLACKOUT_CONTENT"
+ android:protectionLevel="signature" />
+
+ <!-- Allows read only access to phone state with a non dangerous permission,
+ including the information like cellular network type, software version. -->
+ <permission android:name="android.permission.READ_BASIC_PHONE_STATE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
+ android:label="@string/permlab_readBasicPhoneState"
+ android:description="@string/permdesc_readBasicPhoneState"
+ android:protectionLevel="normal" />
+
+ <!-- @SystemApi Allows an application to query over global data in AppSearch.
+ @hide -->
+ <permission android:name="android.permission.READ_GLOBAL_APP_SEARCH_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to query over global data in AppSearch that's visible to the
+ ASSISTANT role. -->
+ <permission android:name="android.permission.READ_ASSISTANT_APP_SEARCH_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to query over global data in AppSearch that's visible to the
+ HOME role. -->
+ <permission android:name="android.permission.READ_HOME_APP_SEARCH_DATA"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an assistive application to perform actions on behalf of users inside of
+ applications.
+ <p>For now, this permission is only granted to the Assistant application selected by
+ the user.
+ <p>Protection level: internal|role
+ -->
+ <permission android:name="android.permission.EXECUTE_APP_ACTION"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to display its suggestions using the autofill framework.
+ <p>For now, this permission is only granted to the Browser application.
+ <p>Protection level: internal|role
+ -->
+ <permission android:name="android.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Allows an application to create virtual devices in VirtualDeviceManager.
+ @hide -->
+ <permission android:name="android.permission.CREATE_VIRTUAL_DEVICE"
+ android:protectionLevel="internal|role" />
+
+ <!-- @SystemApi Must be required by a safety source to send an update using the
+ {@link android.safetycenter.SafetyCenterManager}.
+ <p>Protection level: internal|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE"
+ android:protectionLevel="internal|privileged" />
+
+ <!-- @SystemApi Allows an application to launch device manager setup screens.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.LAUNCH_DEVICE_MANAGER_SETUP"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an application to update certain device management related system
+ resources.
+ @hide -->
+ <permission android:name="android.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES"
+ android:protectionLevel="signature|role" />
+
+ <!-- @SystemApi Allows an app to read whether SafetyCenter is enabled/disabled.
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.READ_SAFETY_CENTER_STATUS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Required to access the safety center internal APIs using the
+ {@link android.safetycenter.SafetyCenterManager}.
+ <p>Protection level: internal|installer|role
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_SAFETY_CENTER"
+ android:protectionLevel="internal|installer|role" />
+
+ <!-- @SystemApi Allows an app to set keep-clear areas without restrictions on the size or
+ number of keep-clear areas (see {@link android.view.View#setPreferKeepClearRects}).
+ When the system arranges floating windows onscreen, it might decide to ignore keep-clear
+ areas from windows, whose owner does not have this permission.
+ @hide
+ -->
+ <permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an app to set gesture exclusion without restrictions on the vertical extent of the
+ exclusions (see {@link android.view.View#setSystemGestureExclusionRects}).
+ @hide
+ -->
+ <permission android:name="android.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION"
+ android:protectionLevel="signature|privileged|recents" />
+
+ <!-- Allows an UID to be visible to the application based on an interaction between the
+ two apps. This permission is not intended to be held by apps.
+ @hide @TestApi -->
+ <permission android:name="android.permission.MAKE_UID_VISIBLE"
+ android:protectionLevel="signature" />
+
+ <!-- Limits the system as the only handler of the QUERY_PACKAGE_RESTART broadcast
+ @hide -->
+ <permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART"
+ android:protectionLevel="signature" />
+ <uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" />
+
+ <!-- Allows financed device kiosk apps to perform actions on the Device Lock service
+ @hide @TestApi @SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES) -->
+ <permission android:name="android.permission.MANAGE_DEVICE_LOCK_STATE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an app to turn on the screen on, e.g. with
+ {@link android.os.PowerManager#ACQUIRE_CAUSES_WAKEUP}.
+ <p>Intended to only be used by home automation apps.
+ -->
+ <permission android:name="android.permission.TURN_SCREEN_ON"
+ android:label="@string/permlab_turnScreenOn"
+ android:description="@string/permdesc_turnScreenOn"
+ android:protectionLevel="signature|privileged|appop" />
+
+ <!-- Allows applications to use the user-initiated jobs API. For more details
+ see {@link android.app.job.JobInfo.Builder#setUserInitiated}.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.RUN_USER_INITIATED_JOBS"
+ android:protectionLevel="normal"/>
+
+ <!-- Allows a browser to invoke the set of credential candidate query apis.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS"
+ android:protectionLevel="normal" />
+
+ <!-- Allows browsers to call on behalf of another app by passing in a custom origin.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ORIGIN"
+ android:protectionLevel="normal"/>
+
+ <!-- Allows specifying candidate credential providers to be queried in Credential Manager
+ get flows, or to be preferred as a default in the Credential Manager create flows.
+ <p>Protection level: normal -->
+ <permission android:name="android.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS"
+ android:protectionLevel="normal"/>
+
+ <!-- Allows permission to use Credential Manager UI for providing and saving credentials
+ @hide -->
+ <permission android:name="android.permission.LAUNCH_CREDENTIAL_SELECTOR"
+ android:protectionLevel="signature" />
+
+ <!-- Allows an app to list Credential Manager providers.
+ @hide
+ -->
+ <permission android:name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS"
+ android:protectionLevel="signature|privileged"/>
+
+ <!-- Allows a system application to be registered with credential manager without
+ having to be enabled by the user.
+ @SystemApi
+ @hide -->
+ <permission android:name="android.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- Allows an application to be able to store and retrieve credentials from a remote
+ device. -->
+ <permission android:name="android.permission.PROVIDE_REMOTE_CREDENTIALS"
+ android:protectionLevel="signature|privileged|role" />
+
+ <!-- Allows an app access to the installer provided app metadata.
+ @SystemApi
+ @hide -->
+ <permission android:name="android.permission.GET_APP_METADATA"
+ android:protectionLevel="signature|installer" />
+
+ <!-- @hide @SystemApi Allows an application to stage HealthConnect's remote data so that
+ HealthConnect can later integrate it. -->
+ <permission android:name="android.permission.STAGE_HEALTH_CONNECT_REMOTE_DATA"
+ android:protectionLevel="signature|knownSigner"
+ android:knownCerts="@array/config_healthConnectRestoreKnownSigners"/>
+
+ <!-- @hide @TestApi Allows an application to clear HealthConnect's staged remote data for
+ testing only. For security reasons, this is a platform-only permission. -->
+ <permission android:name="android.permission.DELETE_STAGED_HEALTH_CONNECT_REMOTE_DATA"
+ android:protectionLevel="signature" />
+
+ <!-- @hide @TestApi Allows CTS tests running in Sandbox mode to launch activities -->
+ <permission android:name="android.permission.START_ACTIVITIES_FROM_SDK_SANDBOX"
+ android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows the holder to call health connect migration APIs.
+ @hide -->
+ <permission android:name="android.permission.MIGRATE_HEALTH_CONNECT_DATA"
+ android:protectionLevel="signature|knownSigner"
+ android:knownCerts="@array/config_healthConnectMigrationKnownSigners" />
+
+ <!-- @SystemApi Allows an app to query apps in clone profile. The permission is
+ bidirectional in nature, i.e. cloned apps would be able to query apps in root user.
+ The permission is not meant for 3P apps as of now.
+ <p>Protection level: signature|privileged
+ @hide
+ -->
+ <permission android:name="android.permission.QUERY_CLONED_APPS"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @hide @SystemApi
+ Allows applications to capture bugreport directly without consent dialog when using the
+ bugreporting API on userdebug/eng build.
+ <p>The application still needs to hold {@link android.permission.DUMP} permission and be
+ bugreport-whitelisted to be able to capture a bugreport using the bugreporting API in the
+ first place. Then, when the corresponding app op of this permission is ALLOWED, the
+ bugreport can be captured directly without going through the consent dialog.
+ <p>Protection level: internal|appop
+ <p>Intended to only be used on userdebug/eng build.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD"
+ android:protectionLevel="internal|appop" />
+
+ <!-- @SystemApi Allows to call APIs that log process lifecycle events
+ @hide -->
+ <permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"
+ android:protectionLevel="signature|module" />
+
+ <!-- @hide Allows the settings app to access GPU service APIs".
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.ACCESS_GPU_SERVICE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows an application to get type of any provider uri.
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.GET_ANY_PROVIDER_TYPE"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows internal applications to read and synchronize non-core flags.
+ Apps without this permission can only read a subset of flags specifically intended
+ for use in "core", (i.e. third party apps). Apps with this permission can define their
+ own flags, and federate those values with other system-level apps.
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.SYNC_FLAGS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows internal applications to override flags in the FeatureFlags service.
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.WRITE_FLAGS"
+ android:protectionLevel="signature" />
+
+ <!-- @hide Allows internal applications to manage displays.
+ <p>This means intercept internal signals about displays being (dis-)connected
+ and being able to enable or disable connected displays.
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.MANAGE_DISPLAYS"
+ android:protectionLevel="signature" />
+
+ <!-- Attribution for Geofencing service. -->
+ <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
+ <!-- Attribution for Country Detector. -->
+ <attribution android:tag="CountryDetector" android:label="@string/country_detector"/>
+ <!-- Attribution for Location service. -->
+ <attribution android:tag="LocationService" android:label="@string/location_service"/>
+ <!-- Attribution for Gnss service. -->
+ <attribution android:tag="GnssService" android:label="@string/gnss_service"/>
+ <!-- Attribution for Sensor Notification service. -->
+ <attribution android:tag="SensorNotificationService"
+ android:label="@string/sensor_notification_service"/>
+ <!-- Attribution for Twilight service. -->
+ <attribution android:tag="TwilightService" android:label="@string/twilight_service"/>
+ <!-- Attribution for Gnss Time Update service. -->
+ <attribution android:tag="GnssTimeUpdateService"
+ android:label="@string/gnss_time_update_service"/>
+ <!-- Attribution for MusicRecognitionManagerService.
+ <p>Not for use by third-party applications.</p> -->
+ <attribution android:tag="MusicRecognitionManagerService"
+ android:label="@string/music_recognition_manager_service"/>
+
+ <application android:process="system"
+ android:persistent="true"
+ android:hasCode="false"
+ android:label="@string/android_system_label"
+ android:allowClearUserData="false"
+ android:backupAgent="com.android.server.backup.SystemBackupAgent"
+ android:killAfterRestore="false"
+ android:icon="@drawable/ic_launcher_android"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.DeviceDefault.Light.DarkActionBar"
+ android:defaultToDeviceProtectedStorage="true"
+ android:forceQueryable="true"
+ android:directBootAware="true">
+ <activity android:name="com.android.internal.app.ChooserActivity"
+ android:theme="@style/Theme.DeviceDefault.Chooser"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:process=":ui"
+ android:exported="true"
+ android:visibleToInstantApps="true">
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.CHOOSER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.VOICE" />
+ </intent-filter>
+ </activity>
+ <activity android:name="com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity"
+ android:exported="false"
+ android:theme="@style/Theme.DeviceDefault.Dialog.Alert.DayNight"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ <intent-filter>
+ <action android:name="com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name="com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity"
+ android:exported="false"
+ android:theme="@style/Theme.DeviceDefault.Resolver"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ <intent-filter>
+ <action android:name="com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name="com.android.internal.app.IntentForwarderActivity"
+ android:finishOnCloseSystemDialogs="true"
+ android:theme="@style/Theme.Translucent.NoTitleBar"
+ android:excludeFromRecents="true"
+ android:label="@string/user_owner_label"
+ android:exported="true"
+ android:visibleToInstantApps="true"
+ >
+ </activity>
+ <activity-alias android:name="com.android.internal.app.ForwardIntentToParent"
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:exported="true"
+ android:label="@string/user_owner_label">
+ </activity-alias>
+ <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
+ android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+ android:icon="@drawable/ic_corp_badge"
+ android:exported="true"
+ android:label="@string/managed_profile_label">
+ </activity-alias>
+ <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
+ android:theme="@style/Theme.DeviceDefault.System.Dialog.Alert"
+ android:label="@string/heavy_weight_switcher_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+ <activity android:name="com.android.internal.app.PlatLogoActivity"
+ android:theme="@style/Theme.DeviceDefault.Wallpaper.NoTitleBar"
+ android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
+ android:icon="@drawable/platlogo"
+ android:process=":ui">
+ </activity>
+ <activity android:name="com.android.internal.app.DisableCarModeActivity"
+ android:theme="@style/Theme.NoDisplay"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="android.accounts.ChooseAccountActivity"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ </activity>
+
+ <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ </activity>
+
+ <activity android:name="android.accounts.ChooseAccountTypeActivity"
+ android:excludeFromRecents="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/choose_account_label"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ </activity>
+
+ <activity android:name="android.accounts.CantAddAccountActivity"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog.NoActionBar"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:theme="@style/Theme.DeviceDefault.Light.DialogWhenLarge"
+ android:process=":ui"
+ android:visibleToInstantApps="true">
+ </activity>
+
+ <activity android:name="android.content.SyncActivityTooManyDeletes"
+ android:theme="@style/Theme.DeviceDefault.Light.Dialog"
+ android:label="@string/sync_too_many_deletes"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.internal.app.ShutdownActivity"
+ android:permission="android.permission.SHUTDOWN"
+ android:theme="@style/Theme.NoDisplay"
+ android:exported="true"
+ android:excludeFromRecents="true">
+ <intent-filter>
+ <action android:name="com.android.internal.intent.action.REQUEST_SHUTDOWN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.REBOOT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.android.internal.app.NetInitiatedActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.internal.app.SystemUserHomeActivity"
+ android:enabled="false"
+ android:process=":ui"
+ android:systemUserOnly="true"
+ android:exported="true"
+ android:theme="@style/Theme.Translucent.NoTitleBar">
+ <intent-filter android:priority="-100">
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME" />
+ </intent-filter>
+ </activity>
+
+ <!-- Activity to prompt user if it's ok to create a new user sandbox for a
+ specified account. -->
+ <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
+ android:excludeFromRecents="true"
+ android:process=":ui"
+ android:exported="true"
+ android:theme="@style/Theme.Dialog.Confirmation">
+ <intent-filter android:priority="1000">
+ <action android:name="android.os.action.CREATE_USER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.android.internal.app.SuspendedAppActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.internal.app.BlockedAppActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:lockTaskMode="always"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.internal.app.LaunchAfterAuthenticationActivity"
+ android:theme="@style/Theme.Translucent.NoTitleBar"
+ android:excludeFromRecents="true"
+ android:process=":ui">
+ </activity>
+
+ <activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true">
+ </activity>
+
+ <activity android:name="com.android.internal.app.HarmfulAppWarningActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:process=":ui"
+ android:label="@string/harmful_app_warning_title"
+ android:exported="false">
+ </activity>
+
+ <activity android:name="com.android.server.notification.NASLearnMoreActivity"
+ android:theme="@style/Theme.Dialog.Confirmation"
+ android:excludeFromRecents="true"
+ android:exported="false">
+ </activity>
+
+ <receiver android:name="com.android.server.BootReceiver"
+ android:exported="true"
+ android:systemUserOnly="true">
+ <intent-filter android:priority="1000">
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.CertPinInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_PINS" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.IntentFirewallInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_INTENT_FIREWALL" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.SmsShortCodesInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_SMS_SHORT_CODES" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.NetworkWatchlistInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_NETWORK_WATCHLIST" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.CarrierProvisioningUrlsInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.CertificateTransparencyLogInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_CT_LOGS" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.LangIdInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_LANG_ID" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.SmartSelectionInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_SMART_SELECTION" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.ConversationActionsInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.intent.action.UPDATE_CONVERSATION_ACTIONS" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.CarrierIdInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.os.action.UPDATE_CARRIER_ID_DB" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.updates.EmergencyNumberDbInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.os.action.UPDATE_EMERGENCY_NUMBER_DB" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.MasterClearReceiver"
+ android:exported="true"
+ android:permission="android.permission.MASTER_CLEAR">
+ <intent-filter
+ android:priority="100" >
+ <!-- For Checkin, Settings, etc.: action=FACTORY_RESET -->
+ <action android:name="android.intent.action.FACTORY_RESET" />
+ <!-- As above until all the references to the deprecated MASTER_CLEAR get updated to
+ FACTORY_RESET. -->
+ <action android:name="android.intent.action.MASTER_CLEAR" />
+
+ <!-- MCS always uses REMOTE_INTENT: category=MASTER_CLEAR -->
+ <action android:name="com.google.android.c2dm.intent.RECEIVE" />
+ <category android:name="android.intent.category.MASTER_CLEAR" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.WallpaperUpdateReceiver"
+ android:exported="true"
+ android:permission="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY">
+ <intent-filter>
+ <action android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY"/>
+ </intent-filter>
+ </receiver>
+
+ <service android:name="android.hardware.location.GeofenceHardwareService"
+ android:permission="android.permission.LOCATION_HARDWARE"
+ android:exported="false" />
+
+ <service android:name="com.android.server.MountServiceIdler"
+ android:exported="true"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.ZramWriteback"
+ android:exported="false"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.backup.FullBackupJob"
+ android:exported="true"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.backup.KeyValueBackupJob"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.content.SyncJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.pm.BackgroundDexOptJobService"
+ android:exported="true"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
+ <service android:name="com.android.server.pm.DynamicCodeLoggingService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
+ <service android:name="com.android.server.PruneInstantAppsJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.storage.DiskStatsLoggingService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.PreloadsFileCacheExpirationJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.camera.CameraStatsJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.usage.UsageStatsIdleService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.net.watchlist.ReportWatchlistJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.display.BrightnessIdleJob"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.people.data.DataMaintenanceService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service android:name="com.android.server.profcollect.ProfcollectForwardingService$ProfcollectBGJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" >
+ </service>
+
+ <service
+ android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:visibleToInstantApps="true"
+ android:exported="true">
+ <meta-data
+ android:name="android.accessibilityservice"
+ android:resource="@xml/autofill_compat_accessibility_service" />
+ </service>
+
+ <service android:name="com.android.server.blob.BlobStoreIdleJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
+ <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
+ android:exported="false">
+ <intent-filter>
+ <action android:name="android.intent.action.LOAD_DATA"/>
+ </intent-filter>
+ </service>
+
+ <provider
+ android:name="com.android.server.textclassifier.IconsContentProvider"
+ android:authorities="com.android.textclassifier.icons"
+ android:singleUser="true"
+ android:enabled="true"
+ android:exported="true">
+ </provider>
+
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml b/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml
new file mode 100644
index 000000000..8a6aa1980
--- /dev/null
+++ b/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml
@@ -0,0 +1,573 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" >
+
+ <!--
+ This file contains the permissions defined by CarService-Builtin(com.android.car)
+ and CarService-updatable(com.[google.]?android.car.updatable). As this is only a
+ resource file, permissions from both packages can be added here.
+ -->
+ <permission-group android:name="android.car.permission-group.CAR_MONITORING"
+ android:icon="@drawable/perm_group_car"
+ android:description="@string/car_permission_desc"
+ android:label="@string/car_permission_label"/>
+ <permission android:name="android.car.permission.CAR_ENERGY"
+ android:permissionGroup="android.car.permission-group.CAR_MONITORING"
+ android:protectionLevel="dangerous"
+ android:label="@string/car_permission_label_energy"
+ android:description="@string/car_permission_desc_energy"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_ENERGY"
+ android:permissionGroup="android.car.permission-group.CAR_MONITORING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_energy"
+ android:description="@string/car_permission_desc_control_car_energy"/>
+ <permission android:name="android.car.permission.READ_DRIVER_MONITORING_SETTINGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_driver_monitoring_settings"
+ android:description="@string/car_permission_desc_read_driver_monitoring_settings"/>
+ <permission android:name="android.car.permission.CONTROL_DRIVER_MONITORING_SETTINGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_driver_monitoring_settings"
+ android:description="@string/car_permission_desc_control_driver_monitoring_settings"/>
+ <permission android:name="android.car.permission.READ_DRIVER_MONITORING_STATES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_driver_monitoring_states"
+ android:description="@string/car_permission_desc_read_driver_monitoring_states"/>
+ <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_adjust_range_remaining"
+ android:description="@string/car_permission_desc_adjust_range_remaining"/>
+ <permission android:name="android.car.permission.CAR_IDENTIFICATION"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_identification"
+ android:description="@string/car_permission_desc_car_identification"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_CLIMATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_hvac"
+ android:description="@string/car_permission_desc_hvac"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_DOORS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_doors"
+ android:description="@string/car_permission_desc_control_car_doors"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_WINDOWS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_windows"
+ android:description="@string/car_permission_desc_control_car_windows"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_MIRRORS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_mirrors"
+ android:description="@string/car_permission_desc_control_car_mirrors"/>
+ <permission android:name="android.car.permission.CONTROL_GLOVE_BOX"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_glove_box"
+ android:description="@string/car_permission_desc_control_glove_box"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_SEATS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_seats"
+ android:description="@string/car_permission_desc_control_car_seats"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_AIRBAGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_airbags"
+ android:description="@string/car_permission_desc_control_car_airbags"/>
+ <permission android:name="android.car.permission.CAR_MILEAGE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_mileage"
+ android:description="@string/car_permission_desc_mileage"/>
+ <permission android:name="android.car.permission.CAR_TIRES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_tires"
+ android:description="@string/car_permission_desc_car_tires"/>
+ <permission android:name="android.car.permission.READ_CAR_STEERING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_steering"
+ android:description="@string/car_permission_desc_car_steering"/>
+ <permission android:name="android.car.permission.READ_CAR_DISPLAY_UNITS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_read_car_display_units"
+ android:description="@string/car_permission_desc_read_car_display_units"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_DISPLAY_UNITS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_control_car_display_units"
+ android:description="@string/car_permission_desc_control_car_display_units"/>
+ <permission android:name="android.car.permission.CAR_SPEED"
+ android:permissionGroup="android.permission-group.LOCATION"
+ android:protectionLevel="dangerous"
+ android:label="@string/car_permission_label_speed"
+ android:description="@string/car_permission_desc_speed"/>
+ <permission android:name="android.car.permission.CAR_ENERGY_PORTS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_energy_ports"
+ android:description="@string/car_permission_desc_car_energy_ports"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_energy_ports"
+ android:description="@string/car_permission_desc_control_car_energy_ports"/>
+ <permission android:name="android.car.permission.CAR_ENGINE_DETAILED"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_engine_detailed"
+ android:description="@string/car_permission_desc_car_engine_detailed"/>
+ <permission android:name="android.car.permission.CAR_DYNAMICS_STATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vehicle_dynamics_state"
+ android:description="@string/car_permission_desc_vehicle_dynamics_state"/>
+ <permission android:name="android.car.permission.CAR_VENDOR_EXTENSION"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vendor_extension"
+ android:description="@string/car_permission_desc_vendor_extension"/>
+ <permission android:name="android.car.permission.CAR_PROJECTION"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_projection"
+ android:description="@string/car_permission_desc_projection"/>
+ <permission android:name="android.car.permission.ACCESS_CAR_PROJECTION_STATUS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_access_projection_status"
+ android:description="@string/car_permission_desc_access_projection_status"/>
+ <permission android:name="android.car.permission.BIND_PROJECTION_SERVICE"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_projection_service"
+ android:description="@string/car_permission_desc_bind_projection_service"/>
+ <permission android:name="android.car.permission.CAR_MOCK_VEHICLE_HAL"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_mock_vehicle_hal"
+ android:description="@string/car_permission_desc_mock_vehicle_hal"/>
+ <permission android:name="android.car.permission.CAR_INFO"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_info"
+ android:description="@string/car_permission_desc_car_info"/>
+ <permission android:name="android.car.permission.PRIVILEGED_CAR_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_privileged_car_info"
+ android:description="@string/car_permission_desc_privileged_car_info"/>
+ <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vendor_permission_info"
+ android:description="@string/car_permission_desc_vendor_permission_info"/>
+ <permission android:name="android.car.permission.MANAGE_REMOTE_DEVICE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_manage_remote_device"
+ android:description="@string/car_permission_desc_manage_remote_device"/>
+ <permission android:name="android.car.permission.MANAGE_OCCUPANT_CONNECTION"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_manage_occupant_connection"
+ android:description="@string/car_permission_desc_manage_occupant_connection"/>
+
+ <!-- Allows an application to read the vehicle exterior environment information. For example,
+ it allows an application to read the vehicle exterior temperature and night mode status.
+ <p>Protection level: normal
+ -->
+ <permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_exterior_environment"
+ android:description="@string/car_permission_desc_car_exterior_environment"/>
+ <permission android:name="android.car.permission.CAR_EPOCH_TIME"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_epoch_time"
+ android:description="@string/car_permission_desc_car_epoch_time"/>
+ <permission android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_exterior_lights"
+ android:description="@string/car_permission_desc_car_exterior_lights"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_exterior_lights"
+ android:description="@string/car_permission_desc_control_car_exterior_lights"/>
+ <permission android:name="android.car.permission.READ_CAR_INTERIOR_LIGHTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_interior_lights"
+ android:description="@string/car_permission_desc_car_interior_lights"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_INTERIOR_LIGHTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_interior_lights"
+ android:description="@string/car_permission_desc_control_car_interior_lights"/>
+ <permission android:name="android.car.permission.CAR_POWER"
+ android:protectionLevel="signature|privileged|vendorPrivileged"
+ android:label="@string/car_permission_label_car_power"
+ android:description="@string/car_permission_desc_car_power"/>
+ <permission android:name="android.car.permission.CAR_POWERTRAIN"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_car_powertrain"
+ android:description="@string/car_permission_desc_car_powertrain"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_POWERTRAIN"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_powertrain"
+ android:description="@string/car_permission_desc_control_car_powertrain"/>
+ <permission android:name="android.car.permission.CAR_NAVIGATION_MANAGER"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_car_navigation_manager"
+ android:description="@string/car_permission_desc_car_navigation_manager"/>
+ <permission android:name="android.car.permission.CAR_DIAGNOSTICS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_diag_read"
+ android:description="@string/car_permission_desc_diag_read"/>
+ <permission android:name="android.car.permission.CLEAR_CAR_DIAGNOSTICS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_diag_clear"
+ android:description="@string/car_permission_desc_diag_clear"/>
+ <permission android:name="android.car.permission.BIND_VMS_CLIENT"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_vms_client"
+ android:description="@string/car_permission_desc_bind_vms_client"/>
+ <permission android:name="android.car.permission.VMS_PUBLISHER"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vms_publisher"
+ android:description="@string/car_permission_desc_vms_publisher"/>
+ <permission android:name="android.car.permission.VMS_SUBSCRIBER"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_vms_subscriber"
+ android:description="@string/car_permission_desc_vms_subscriber"/>
+ <permission android:name="android.car.permission.CAR_DRIVING_STATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_driving_state"
+ android:description="@string/car_permission_desc_driving_state"/>
+ <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_use_telemetry_service"
+ android:description="@string/car_permission_desc_use_telemetry_service"/>
+ <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_request_evs_activity"
+ android:description="@string/car_permission_desc_request_evs_activity"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_evs_activity"
+ android:description="@string/car_permission_desc_control_evs_activity"/>
+ <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_use_evs_camera"
+ android:description="@string/car_permission_desc_use_evs_camera"/>
+ <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_monitor_evs_status"
+ android:description="@string/car_permission_desc_monitor_evs_status"/>
+ <permission android:name="android.car.permission.CONTROL_APP_BLOCKING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_app_blocking"
+ android:description="@string/car_permission_desc_control_app_blocking"/>
+ <permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_audio_volume"
+ android:description="@string/car_permission_desc_audio_volume"/>
+ <permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_audio_settings"
+ android:description="@string/car_permission_desc_audio_settings"/>
+ <permission android:name="android.car.permission.RECEIVE_CAR_AUDIO_DUCKING_EVENTS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_receive_ducking"
+ android:description="@string/car_permission_desc_receive_ducking"/>
+ <permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_instrument_cluster_rendering"
+ android:description="@string/car_permission_desc_bind_instrument_cluster_rendering"/>
+ <permission android:name="android.car.permission.BIND_CAR_INPUT_SERVICE"
+ android:protectionLevel="signature"
+ android:label="@string/car_permission_label_bind_input_service"
+ android:description="@string/car_permission_desc_bind_input_service"/>
+ <permission android:name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_car_display_in_cluster"
+ android:description="@string/car_permission_desc_car_display_in_cluster"/>
+ <permission android:name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_car_cluster_control"
+ android:description="@string/car_permission_desc_car_cluster_control"/>
+ <permission android:name="android.car.permission.CAR_MONITOR_CLUSTER_NAVIGATION_STATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_car_monitor_cluster_navigation_state"
+ android:description="@string/car_permission_desc_car_monitor_cluster_navigation_state"/>
+ <permission android:name="android.car.permission.CAR_HANDLE_USB_AOAP_DEVICE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_handle_usb_aoap_device"
+ android:description="@string/car_permission_desc_car_handle_usb_aoap_device"/>
+ <permission android:name="android.car.permission.CAR_UX_RESTRICTIONS_CONFIGURATION"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_ux_restrictions_configuration"
+ android:description="@string/car_permission_desc_car_ux_restrictions_configuration"/>
+ <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_car_occupant_awareness_state"
+ android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
+ <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_access_private_display_id"
+ android:description="@string/car_permission_desc_access_private_display_id"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_occupant_awareness_system"
+ android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
+ <permission android:name="android.car.permission.STORAGE_MONITORING"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_storage_monitoring"
+ android:description="@string/car_permission_desc_storage_monitoring"/>
+ <permission android:name="android.car.permission.CAR_ENROLL_TRUST"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_enroll_trust"
+ android:description="@string/car_permission_desc_enroll_trust"/>
+ <permission android:name="android.car.permission.CAR_TEST_SERVICE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_car_test_service"
+ android:description="@string/car_permission_desc_car_test_service"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_features"
+ android:description="@string/car_permission_desc_control_car_features"/>
+ <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_use_car_watchdog"
+ android:description="@string/car_permission_desc_use_car_watchdog"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_watchdog_config"
+ android:description="@string/car_permission_desc_control_car_watchdog_config"/>
+ <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_collect_car_watchdog_metrics"
+ android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_window"
+ android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_window"
+ android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_door"
+ android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_door"
+ android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_info"
+ android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_info"
+ android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_light"
+ android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_light"
+ android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_1"
+ android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_1"
+ android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_2"
+ android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_2"
+ android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_3"
+ android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_3"
+ android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_4"
+ android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_4"
+ android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_5"
+ android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_5"
+ android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_6"
+ android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_6"
+ android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_7"
+ android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_7"
+ android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_8"
+ android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_8"
+ android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_9"
+ android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_9"
+ android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_get_car_vendor_category_10"
+ android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_set_car_vendor_category_10"
+ android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
+ <permission android:name="android.car.permission.CAR_MONITOR_INPUT"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_monitor_input"
+ android:description="@string/car_permission_desc_monitor_input"/>
+ <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_read_car_power_policy"
+ android:description="@string/car_permission_desc_read_car_power_policy"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
+ android:protectionLevel="signature|privileged|vendorPrivileged"
+ android:label="@string/car_permission_label_control_car_power_policy"
+ android:description="@string/car_permission_desc_control_car_power_policy"/>
+ <permission android:name="android.car.permission.CONTROL_SHUTDOWN_PROCESS"
+ android:protectionLevel="signature|privileged|vendorPrivileged"
+ android:label="@string/car_permission_label_adjust_shutdown_process"
+ android:description="@string/car_permission_desc_adjust_shutdown_process"/>
+ <permission android:name="android.car.permission.TEMPLATE_RENDERER"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_template_renderer"
+ android:description="@string/car_permission_desc_template_renderer"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_APP_LAUNCH"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_car_app_launch"
+ android:description="@string/car_permission_desc_control_car_app_launch"/>
+ <permission android:name="android.car.permission.MANAGE_THREAD_PRIORITY"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_manage_thread_priority"
+ android:description="@string/car_permission_desc_manage_thread_priority"/>
+ <permission android:name="android.car.permission.BIND_OEM_CAR_SERVICE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_bind_oem_car_service"
+ android:description="@string/car_permission_desc_bind_oem_car_service"/>
+ <permission android:name="android.car.permission.MANAGE_OCCUPANT_ZONE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_manage_occupant_zone"
+ android:description="@string/car_permission_desc_manage_occupant_zone"/>
+ <permission android:name="android.car.permission.CONTROL_STEERING_WHEEL"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_steering_wheel"
+ android:description="@string/car_permission_desc_control_steering_wheel"/>
+ <permission android:name="android.car.permission.USE_REMOTE_ACCESS"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_use_remote_access"
+ android:description="@string/car_permission_desc_use_remote_access"/>
+ <permission android:name="android.car.permission.CONTROL_REMOTE_ACCESS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_remote_access"
+ android:description="@string/car_permission_desc_control_remote_access"/>
+ <permission android:name="android.car.permission.READ_ADAS_SETTINGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_adas_settings"
+ android:description="@string/car_permission_desc_read_adas_settings"/>
+ <permission android:name="android.car.permission.CONTROL_ADAS_SETTINGS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_adas_settings"
+ android:description="@string/car_permission_desc_control_adas_settings"/>
+ <permission android:name="android.car.permission.READ_ADAS_STATES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_adas_states"
+ android:description="@string/car_permission_desc_read_adas_states"/>
+ <permission android:name="android.car.permission.CONTROL_ADAS_STATES"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_adas_states"
+ android:description="@string/car_permission_desc_control_adas_states"/>
+ <permission android:name="android.car.permission.ACCESS_MIRRORED_SURFACE"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_access_mirrored_surface"
+ android:description="@string/car_permission_desc_access_mirrored_surface"/>
+ <permission android:name="android.car.permission.MIRROR_DISPLAY"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_mirror_display"
+ android:description="@string/car_permission_desc_mirror_display"/>
+ <permission android:name="android.car.permission.REGISTER_CAR_SYSTEM_UI_PROXY"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_register_car_system_ui_proxy"
+ android:description="@string/car_permission_desc_register_car_system_ui_proxy"/>
+ <permission android:name="android.car.permission.MANAGE_CAR_SYSTEM_UI"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_manage_car_system_ui"
+ android:description="@string/car_permission_desc_manage_car_system_ui"/>
+ <permission android:name="android.car.permission.READ_WINDSHIELD_WIPERS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_read_windshield_wipers"
+ android:description="@string/car_permission_desc_read_windshield_wipers"/>
+ <permission android:name="android.car.permission.CONTROL_WINDSHIELD_WIPERS"
+ android:protectionLevel="signature|privileged"
+ android:label="@string/car_permission_label_control_windshield_wipers"
+ android:description="@string/car_permission_desc_control_windshield_wipers"/>
+</manifest>
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/CommandBroadcastReceiver.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/CommandBroadcastReceiver.java
new file mode 100644
index 000000000..02138f36f
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/CommandBroadcastReceiver.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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 andf
+ * limitations under the License.
+ */
+
+package android.permissionpolicy.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import javax.annotation.Nullable;
+
+public class CommandBroadcastReceiver extends BroadcastReceiver {
+
+ private static @Nullable OnCommandResultListener sOnCommandResultListener;
+
+ public interface OnCommandResultListener {
+ void onCommandResult(@Nullable Intent result);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final OnCommandResultListener listener;
+ synchronized (CommandBroadcastReceiver.class) {
+ listener = sOnCommandResultListener;
+ }
+ if (listener != null) {
+ listener.onCommandResult(intent);
+ }
+ }
+
+ public static void setOnCommandResultListener(@Nullable OnCommandResultListener listener) {
+ synchronized (CommandBroadcastReceiver.class) {
+ sOnCommandResultListener = listener;
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java
new file mode 100644
index 000000000..d8dc11a14
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ContactsProviderTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 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.permissionpolicy.cts;
+
+import android.content.ContentValues;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.ContactsContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify that deprecated contacts permissions are not enforced.
+ */
+@AppModeFull(reason = "Instant apps cannot get the READ_CONTACTS/WRITE_CONTACTS permissions")
+public class ContactsProviderTest extends AndroidTestCase {
+
+ /**
+ * Verifies that query(ContactsContract.Contacts.CONTENT_URI) only requires
+ * permission {@link android.Manifest.permission#READ_CONTACTS}.
+ */
+ @SmallTest
+ public void testQueryContacts() {
+ getContext().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
+ null, null, null, null);
+ }
+
+ /**
+ * Verifies that insert(ContactsContract.Contacts.CONTENT_URI) only requires
+ * permission {@link android.Manifest.permission#WRITE_CONTACTS}.
+ */
+ @SmallTest
+ public void testInsertContacts() {
+ try {
+ getContext().getContentResolver().insert(ContactsContract.Contacts.CONTENT_URI,
+ new ContentValues());
+ } catch (SecurityException e) {
+ fail("insert(ContactsContract.Contacts.CONTENT_URI) threw SecurityException");
+ } catch (UnsupportedOperationException e) {
+ // It is okay for this fail in this manner.
+ }
+ }
+
+ /**
+ * Verifies that query(ContactsContract.Profile.CONTENT_URI) only requires
+ * permission {@link android.Manifest.permission#READ_CONTACTS}.
+ */
+ @SmallTest
+ public void testQueryProfile() {
+ getContext().getContentResolver().query(ContactsContract.Profile.CONTENT_URI,
+ null, null, null, null);
+ }
+
+ /**
+ * Verifies that insert(ContactsContract.Profile.CONTENT_URI) only requires
+ * permission {@link android.Manifest.permission#WRITE_CONTACTS}. The provider won't
+ * actually let us execute this. But at least it shouldn't throw a security exception.
+ */
+ @SmallTest
+ public void testInsertProfile() {
+ try {
+ getContext().getContentResolver().insert(ContactsContract.Profile.CONTENT_URI,
+ new ContentValues(0));
+ } catch (SecurityException e) {
+ fail("insert(ContactsContract.Profile.CONTENT_URI) threw SecurityException");
+ } catch (UnsupportedOperationException e) {
+ // It is okay for this fail in this manner.
+ }
+ }
+
+ /**
+ * Verifies that update(ContactsContract.Profile.CONTENT_URI) only requires
+ * permission {@link android.Manifest.permission#WRITE_CONTACTS}.
+ */
+ @SmallTest
+ public void testUpdateProfile() {
+ getContext().getContentResolver().update(ContactsContract.Profile.CONTENT_URI,
+ new ContentValues(0), null, null);
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/IntelligenceRolesPolicyTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/IntelligenceRolesPolicyTest.java
new file mode 100644
index 000000000..e2cfe86ca
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/IntelligenceRolesPolicyTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.permissionpolicy.cts;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.R;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+@AppModeFull(reason = "Instant apps cannot read the system servers permission")
+@RunWith(Parameterized.class)
+public class IntelligenceRolesPolicyTest {
+ private final int mConfigKey;
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection intelligenceRoles() {
+ return Arrays.asList(new Object[][]{
+ {"systemUiIntelligence", R.string.config_systemUiIntelligence},
+ {"systemAmbientAudioIntelligence", R.string.config_systemAmbientAudioIntelligence},
+ {"systemAudioIntelligence", R.string.config_systemAudioIntelligence},
+ {"systemNotificationIntelligence", R.string.config_systemNotificationIntelligence},
+ {"systemTextIntelligence", R.string.config_systemTextIntelligence},
+ {"systemVisualIntelligence", R.string.config_systemVisualIntelligence},
+ });
+ }
+
+ public IntelligenceRolesPolicyTest(String unusedName, int configKey) {
+ mConfigKey = configKey;
+ }
+
+ @Test
+ public void testNoInternetPermissionRequested() throws Exception {
+ assumeTrue(ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S));
+
+ String packageName = sContext.getResources().getString(mConfigKey);
+ assumeTrue(!Strings.isNullOrEmpty(packageName));
+
+ List<String> requestedPermissions;
+
+ try {
+ requestedPermissions = getRequestedPermissions(sContext, packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ // A package is not found, despite overlay config pointing to it. Strictly speaking that
+ // means that the policy for being an intelligence role is fulfilled.
+ return;
+ }
+
+ assertWithMessage("Package " + packageName + "MUST NOT request INTERNET permission. "
+ + "Instead packages MUST access the internet through well-defined APIs in an open "
+ + "source project.")
+ .that(requestedPermissions)
+ .doesNotContain(android.Manifest.permission.INTERNET);
+ }
+
+ private static List<String> getRequestedPermissions(Context context, String pkg)
+ throws PackageManager.NameNotFoundException {
+ PackageInfo packageInfo = context.getPackageManager()
+ .getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
+
+ return Arrays.asList(packageInfo.requestedPermissions);
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java
new file mode 100644
index 000000000..0f7638694
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoCaptureAudioOutputPermissionTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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.permissionpolicy.cts;
+
+import android.content.pm.PackageManager;
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder.AudioSource;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify the capture system video output permission requirements.
+ */
+public class NoCaptureAudioOutputPermissionTest extends AndroidTestCase {
+ /**
+ * Verify that the AudioRecord constructor fails to create a recording object
+ * when the app does not have permission to capture audio output.
+ * For the purposes of this test, the app must already have the normal audio
+ * record permission, just not the capture audio output permission.
+ * <p>Requires permission:
+ * {@link android.Manifest.permission#RECORD_AUDIO} and
+ * {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT}.
+ */
+ @SmallTest
+ public void testCreateAudioRecord() {
+ int bufferSize = AudioRecord.getMinBufferSize(44100,
+ AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
+
+ if (bufferSize <= 0)
+ {
+ // getMinBufferSize() returns an invalid buffer size.
+ // That could be because there is no microphone. In that case,
+ // use this buffer size to test AudioRecord creation.
+ PackageManager packageManager = mContext.getPackageManager();
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
+ bufferSize = 44100;
+ }
+ }
+
+ // The attempt to create the AudioRecord object succeeds even if the
+ // app does not have permission, but the object is not usable.
+ // The API should probably throw SecurityException but it was not originally
+ // designed to do that and it's not clear we can change it now.
+ AudioRecord record = new AudioRecord(AudioSource.REMOTE_SUBMIX, 44100,
+ AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
+ try {
+ assertTrue("AudioRecord state should not be INITIALIZED because the application"
+ + "does not have permission to access the remote submix source",
+ record.getState() != AudioRecord.STATE_INITIALIZED);
+ } finally {
+ record.release();
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoProcessOutgoingCallPermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoProcessOutgoingCallPermissionTest.java
new file mode 100644
index 000000000..989c927e1
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoProcessOutgoingCallPermissionTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009 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.permissionpolicy.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.platform.test.annotations.AppModeFull;
+import android.telecom.TelecomManager;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Verify that processing outgoing calls requires Permission.
+ */
+@AppModeFull(reason = "Instant apps cannot hold PROCESS_OUTGOING_CALL")
+public class NoProcessOutgoingCallPermissionTest {
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+
+ // Time to wait for call to be placed.
+ private static final int CALL_START_WAIT_TIME_SEC = 30;
+ // Time to wait for a broadcast to be received after we verify that the test app which has
+ // the proper permission got the broadcast
+ private static final int POST_CALL_START_WAIT_TIME_SEC = 5;
+
+ private static final String APK_INSTALL_LOCATION =
+ "/data/local/tmp/cts-permissionpolicy/CtsProcessOutgoingCalls.apk";
+ private static final String LOG_TAG = "NoProcessOutgoingCallPermissionTest";
+
+ private static final String ACTION_TEST_APP_RECEIVED_CALL =
+ "android.permissionpolicy.cts.TEST_APP_RECEIVED_CALL";
+ private static final String TEST_PKG_NAME = "android.permissionpolicy.cts.receivecallbroadcast";
+
+ private final CountDownLatch mTestAppBroadcastLatch = new CountDownLatch(1);
+ private final CountDownLatch mSystemBroadcastLatch = new CountDownLatch(1);
+
+ private void callPhone() {
+ Uri uri = Uri.parse("tel:123456");
+ Intent intent = new Intent(Intent.ACTION_CALL, uri);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ Log.i(LOG_TAG, "Called phone: " + uri.toString());
+ }
+
+ /**
+ * Verify that to process an outgoing call requires Permission.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS}
+ */
+ // TODO: add back to LargeTest when test can cancel initiated call
+ @Test
+ public void testProcessOutgoingCall() throws InterruptedException {
+ final PackageManager pm = mContext.getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) ||
+ !pm.hasSystemFeature(PackageManager.FEATURE_SIP_VOIP)) {
+ return;
+ }
+
+ OutgoingCallBroadcastReceiver rcvr = new OutgoingCallBroadcastReceiver();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL);
+ filter.addAction(ACTION_TEST_APP_RECEIVED_CALL);
+ mContext.registerReceiver(rcvr, filter, Context.RECEIVER_EXPORTED);
+ // start the test app, so that it can receive the broadcast
+ mContext.startActivity(new Intent().setComponent(new ComponentName(TEST_PKG_NAME,
+ TEST_PKG_NAME + ".ProcessOutgoingCallReceiver$BaseActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+
+ callPhone();
+
+ boolean testAppGotBroadcast =
+ mTestAppBroadcastLatch.await(CALL_START_WAIT_TIME_SEC, TimeUnit.SECONDS);
+ Assert.assertTrue("Expected test app to receive broadcast within "
+ + CALL_START_WAIT_TIME_SEC + " seconds", testAppGotBroadcast);
+ boolean testClassGotBroadcast =
+ mSystemBroadcastLatch.await(POST_CALL_START_WAIT_TIME_SEC, TimeUnit.SECONDS);
+ Assert.assertFalse("Outgoing call processed without proper permissions",
+ testClassGotBroadcast);
+ }
+
+ @Before
+ public void installApp() {
+ String installResult = runShellCommandOrThrow("pm install -g " + APK_INSTALL_LOCATION);
+ assertThat(installResult.trim()).isEqualTo("Success");
+ }
+
+ @After
+ public void endCall() {
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ mContext.getSystemService(TelecomManager.class).endCall();
+ });
+ runShellCommand("pm uninstall " + TEST_PKG_NAME);
+ }
+
+ public class OutgoingCallBroadcastReceiver extends BroadcastReceiver {
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_TEST_APP_RECEIVED_CALL.equals(intent.getAction())) {
+ mTestAppBroadcastLatch.countDown();
+ return;
+ }
+ Bundle xtrs = intent.getExtras();
+ Log.e(LOG_TAG, xtrs.toString());
+ mSystemBroadcastLatch.countDown();
+ }
+ }
+
+}
+
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java
new file mode 100644
index 000000000..c3a29ccb3
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoReceiveSmsPermissionTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2009 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.permissionpolicy.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
+import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Verify Sms and Mms cannot be received without required permissions.
+ * Uses {@link android.telephony.SmsManager}.
+ */
+@AppModeFull(reason = "Instant apps cannot get the SEND_SMS permission")
+@SystemUserOnly(reason = "Secondary users have the DISALLOW_SMS user restriction")
+public class NoReceiveSmsPermissionTest extends AndroidTestCase {
+
+ private static final int SMS_DELIVERED_WAIT_TIME_MILLIS = 4000;
+ private static final String TELEPHONY_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
+ private static final String MESSAGE_STATUS_RECEIVED_ACTION =
+ "com.android.cts.permission.sms.MESSAGE_STATUS_RECEIVED_ACTION";
+ private static final String MESSAGE_SENT_ACTION =
+ "com.android.cts.permission.sms.MESSAGE_SENT";
+ private static final String APP_SPECIFIC_SMS_RECEIVED_ACTION =
+ "com.android.cts.permission.sms.APP_SPECIFIC_SMS_RECEIVED";
+
+
+ private static final String LOG_TAG = "NoReceiveSmsPermissionTest";
+
+ private Semaphore mSemaphore = new Semaphore(0);
+
+ /**
+ * Verify that SmsManager.sendTextMessage requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#SEND_SMS}.
+ *
+ * Note: this test requires that the device under test reports a valid phone number
+ */
+ public void testReceiveTextMessage() {
+ PackageManager packageManager = mContext.getPackageManager();
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ // register our test receiver to receive SMSs. This won't throw a SecurityException,
+ // so test needs to wait to determine if it actual receives an SMS
+ // admittedly, this is a weak verification
+ // this test should be used in conjunction with a test that verifies an SMS can be
+ // received successfully using the same logic if all permissions are in place
+ IllegalSmsReceiver receiver = new IllegalSmsReceiver();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(TELEPHONY_SMS_RECEIVED);
+ filter.addAction(MESSAGE_SENT_ACTION);
+ filter.addAction(MESSAGE_STATUS_RECEIVED_ACTION);
+
+ getContext().registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
+ sendSMSToSelf("test");
+
+ waitForForEvents(mSemaphore, 1);
+ assertTrue("[RERUN] Sms not sent successfully. Check signal.",
+ receiver.isMessageSent());
+ assertFalse("Sms received without proper permissions", receiver.isSmsReceived());
+ }
+
+ /**
+ * Verify that without {@link android.Manifest.permission#RECEIVE_SMS} that an SMS sent
+ * containing a nonce from {@link SmsManager#createAppSpecificSmsToken} is delivered
+ * to the app.
+ */
+ public void testAppSpecificSmsToken() {
+ PackageManager packageManager = mContext.getPackageManager();
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+
+ AppSpecificSmsReceiver receiver = new AppSpecificSmsReceiver();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(TELEPHONY_SMS_RECEIVED);
+ filter.addAction(MESSAGE_SENT_ACTION);
+ filter.addAction(MESSAGE_STATUS_RECEIVED_ACTION);
+ filter.addAction(APP_SPECIFIC_SMS_RECEIVED_ACTION);
+ getContext().registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
+
+ PendingIntent receivedIntent = PendingIntent.getBroadcast(getContext(), 0,
+ new Intent(APP_SPECIFIC_SMS_RECEIVED_ACTION)
+ .setPackage(getContext().getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
+
+ String token = SmsManager.getDefault().createAppSpecificSmsToken(receivedIntent);
+ String message = "test message, token=" + token;
+ sendSMSToSelf(message);
+
+ waitForForEvents(mSemaphore, 1);
+ assertTrue("[RERUN] Sms not sent successfully. Check signal.",
+ receiver.isMessageSent());
+ assertFalse("Sms received without proper permissions", receiver.isSmsReceived());
+ waitForForEvents(mSemaphore, 1);
+ assertTrue("App specific SMS intent not triggered", receiver.isAppSpecificSmsReceived());
+ }
+
+ private boolean waitForForEvents(Semaphore semaphore, int expectedNumberOfEvents) {
+ for (int i = 0; i < expectedNumberOfEvents; i++) {
+ try {
+ if (!semaphore.tryAcquire(SMS_DELIVERED_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS)) {
+ return false;
+ }
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void sendSMSToSelf(String message) {
+ PendingIntent sentIntent = PendingIntent.getBroadcast(getContext(), 0,
+ new Intent(MESSAGE_SENT_ACTION).setPackage(getContext().getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
+ PendingIntent deliveryIntent = PendingIntent.getBroadcast(getContext(), 0,
+ new Intent(MESSAGE_STATUS_RECEIVED_ACTION)
+ .setPackage(getContext().getPackageName()),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
+
+ SubscriptionManager subscription = (SubscriptionManager)
+ getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ int subscriptionId = subscription.getActiveDataSubscriptionId();
+
+ assertFalse("[RERUN] No active telephony subscription. Check there is one enabled.",
+ subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ // get current phone number
+ String currentNumber = subscription.getPhoneNumber(subscriptionId);
+
+ // fallback to getActiveSubscriptionInfo if number is empty
+ if (TextUtils.isEmpty(currentNumber)) {
+ SubscriptionInfo subInfo = subscription.getActiveSubscriptionInfo(subscriptionId);
+
+ assertTrue("[RERUN] No info for the active telephony subscription.",
+ subInfo != null);
+ currentNumber = subInfo.getNumber();
+ }
+ assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.",
+ TextUtils.isEmpty(currentNumber));
+
+ Log.i(LOG_TAG, String.format("Sending SMS to self: %s", currentNumber));
+ sendSms(currentNumber, message, sentIntent, deliveryIntent);
+ }
+
+ protected void sendSms(String currentNumber, String text, PendingIntent sentIntent,
+ PendingIntent deliveryIntent) {
+ SmsManager.getDefault().sendTextMessage(currentNumber, null, text, sentIntent,
+ deliveryIntent);
+ }
+
+ /**
+ * A receiver that tracks if message was sent and received
+ */
+ public class IllegalSmsReceiver extends BroadcastReceiver {
+
+ private boolean mIsSmsReceived = false;
+ private boolean mIsMessageSent = false;
+
+ public void onReceive(Context context, Intent intent) {
+ if (TELEPHONY_SMS_RECEIVED.equals(intent.getAction())) {
+ // this is bad, received sms without having SMS permission
+ setSmsReceived();
+ } else if (MESSAGE_STATUS_RECEIVED_ACTION.equals(intent.getAction())) {
+ handleResultCode(getResultCode(), "delivery");
+ } else if (MESSAGE_SENT_ACTION.equals(intent.getAction())) {
+ handleResultCode(getResultCode(), "sent");
+ } else {
+ Log.w(LOG_TAG, String.format("unknown intent received: %s", intent.getAction()));
+ }
+
+ }
+
+ public boolean isSmsReceived() {
+ return mIsSmsReceived;
+ }
+
+ private synchronized void setSmsReceived() {
+ mIsSmsReceived = true;
+ notify();
+ }
+
+ public boolean isMessageSent() {
+ return mIsMessageSent;
+ }
+
+ private void handleResultCode(int resultCode, String action) {
+ if (resultCode == Activity.RESULT_OK) {
+ Log.i(LOG_TAG, String.format("message %1$s successful", action));
+ setMessageSentSuccess();
+ } else {
+ setMessageSentFailure();
+ String reason = getErrorReason(resultCode);
+ Log.e(LOG_TAG, String.format("message %1$s failed: %2$s", action, reason));
+ }
+ }
+
+ private synchronized void setMessageSentSuccess() {
+ mIsMessageSent = true;
+ // set this to true, but don't notify receiver since we don't know if message received
+ // yet
+ }
+
+ private synchronized void setMessageSentFailure() {
+ mIsMessageSent = false;
+ // test environment failure, notify observer so it can stop listening
+ // TODO: should test retry?
+ notify();
+ }
+
+ private String getErrorReason(int resultCode) {
+ switch (resultCode) {
+ case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
+ return "generic failure";
+ case SmsManager.RESULT_ERROR_NO_SERVICE:
+ return "no service";
+ case SmsManager.RESULT_ERROR_NULL_PDU:
+ return "null pdu";
+ case SmsManager.RESULT_ERROR_RADIO_OFF:
+ return "Radio off";
+ }
+ return "unknown";
+ }
+ }
+
+ public class AppSpecificSmsReceiver extends IllegalSmsReceiver {
+ private boolean mAppSpecificSmsReceived = false;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (APP_SPECIFIC_SMS_RECEIVED_ACTION.equals(intent.getAction())) {
+ mAppSpecificSmsReceived = true;
+ } else {
+ super.onReceive(context, intent);
+ }
+ try {
+ mSemaphore.release();
+ } catch (Exception ex) {
+ Log.e(LOG_TAG, "mSemaphore: Got exception in releasing semaphore, ex=" + ex);
+ }
+ }
+
+ public boolean isAppSpecificSmsReceived() {
+ return mAppSpecificSmsReceived;
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoWriteSecureSettingsPermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoWriteSecureSettingsPermissionTest.java
new file mode 100644
index 000000000..2e4a806b6
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/NoWriteSecureSettingsPermissionTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 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.permissionpolicy.cts;
+
+import android.Manifest;
+import android.content.ContentValues;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+
+/**
+ * Verify secure settings cannot be written to without required permissions.
+ */
+public class NoWriteSecureSettingsPermissionTest extends AndroidTestCase {
+
+ /**
+ * Verify that write to secure settings requires permissions.
+ * This test app must have WRITE_SETTINGS permission but not WRITE_SECURE_SETTINGS
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
+ */
+ public void testWriteSecureSettings() {
+ try {
+ ContentValues values = new ContentValues();
+ values.put(Settings.Secure.NAME, Settings.Secure.ACCESSIBILITY_ENABLED);
+ values.put(Settings.Secure.VALUE, Boolean.TRUE);
+ getContext().getContentResolver().insert(Settings.Secure.CONTENT_URI, values);
+ fail("expected SecurityException requiring "
+ + Manifest.permission.WRITE_SECURE_SETTINGS);
+ } catch (SecurityException expected) {
+ /* do nothing */
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java
new file mode 100644
index 000000000..b02b32f22
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionMaxSdkVersionTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.permission.cts;
+
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Verify permission behaviors with android:maxSdkVersion
+ */
+public class PermissionMaxSdkVersionTest extends AndroidTestCase {
+ // These two permission names must match the corresponding <uses-permission>
+ // declarations in the test app manifest.
+ static final String UNGRANTABLE_PERMISSION = "android.permission.INTERNET";
+ static final String GRANTABLE_PERMISSION = "android.permission.ACCESS_NETWORK_STATE";
+
+ /**
+ * Verify that with android:maxSdkVersion set to a previous API level,
+ * the permission is not being granted.
+ */
+ @SmallTest
+ public void testMaxSdkInPast() {
+ int result = mContext.checkPermission(UNGRANTABLE_PERMISSION,
+ Process.myPid(), Process.myUid());
+ assertEquals("Permissions with maxSdkVersion in the past should not be granted",
+ result,
+ PackageManager.PERMISSION_DENIED);
+ }
+
+ /**
+ * Verify that with android:maxSdkVersion set to a future API level,
+ * the permission is being granted.
+ */
+ @SmallTest
+ public void testMaxSdkInFuture() {
+ int result = mContext.checkPermission(GRANTABLE_PERMISSION,
+ Process.myPid(), Process.myUid());
+ assertEquals("Permissions with maxSdkVersion in the future should be granted",
+ result,
+ PackageManager.PERMISSION_GRANTED);
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionPolicyTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionPolicyTest.java
new file mode 100644
index 000000000..94bd2be1b
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PermissionPolicyTest.java
@@ -0,0 +1,533 @@
+/*
+* Copyright (C) 2015 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.permissionpolicy.cts;
+
+import static android.content.pm.PermissionInfo.FLAG_INSTALLED;
+import static android.content.pm.PermissionInfo.PROTECTION_MASK_BASE;
+import static android.os.Build.VERSION.SECURITY_PATCH;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.platform.test.annotations.AppModeFull;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.modules.utils.build.SdkLevel;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Tests for permission policy on the platform.
+ */
+@AppModeFull(reason = "Instant apps cannot read the system servers permission")
+@RunWith(AndroidJUnit4.class)
+public class PermissionPolicyTest {
+ private static final Date HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE = parseDate("2017-11-01");
+ private static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PERMISSION
+ = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
+
+ private static final Date MANAGE_COMPANION_DEVICES_PATCH_DATE = parseDate("2020-07-01");
+ private static final String MANAGE_COMPANION_DEVICES_PERMISSION
+ = "android.permission.MANAGE_COMPANION_DEVICES";
+
+ private static final String LOG_TAG = "PermissionProtectionTest";
+
+ private static final String PLATFORM_PACKAGE_NAME = "android";
+
+ private static final String PLATFORM_ROOT_NAMESPACE = "android.";
+
+ private static final String TAG_PERMISSION = "permission";
+ private static final String TAG_PERMISSION_GROUP = "permission-group";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_PERMISSION_GROUP = "permissionGroup";
+ private static final String ATTR_PERMISSION_FLAGS = "permissionFlags";
+ private static final String ATTR_PROTECTION_LEVEL = "protectionLevel";
+ private static final String ATTR_BACKGROUND_PERMISSION = "backgroundPermission";
+
+ private static final Context sContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ @Test
+ public void shellIsOnlySystemAppThatRequestsRevokePostNotificationsWithoutKill() {
+ List<PackageInfo> pkgs = sContext.getPackageManager().getInstalledPackages(
+ PackageManager.PackageInfoFlags.of(
+ PackageManager.GET_PERMISSIONS | PackageManager.MATCH_ALL));
+ int shellUid = Process.myUserHandle().getUid(Process.SHELL_UID);
+ for (PackageInfo pkg : pkgs) {
+ Assert.assertFalse(pkg.applicationInfo.uid != shellUid
+ && hasRevokeNotificationNoKillPermission(pkg));
+ }
+ }
+
+ @Test
+ public void platformPermissionPolicyIsUnaltered() throws Exception {
+ Map<String, PermissionInfo> declaredPermissionsMap =
+ getPermissionsForPackage(sContext, PLATFORM_PACKAGE_NAME);
+
+ List<String> offendingList = new ArrayList<>();
+
+ List<PermissionGroupInfo> declaredGroups = sContext.getPackageManager()
+ .getAllPermissionGroups(0);
+ Set<String> declaredGroupsSet = new ArraySet<>();
+ for (PermissionGroupInfo declaredGroup : declaredGroups) {
+ declaredGroupsSet.add(declaredGroup.name);
+ }
+
+ Set<String> expectedPermissionGroups = loadExpectedPermissionGroupNames(
+ R.raw.android_manifest);
+ List<ExpectedPermissionInfo> expectedPermissions = loadExpectedPermissions(
+ R.raw.android_manifest);
+
+ if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ expectedPermissions.addAll(loadExpectedPermissions(R.raw.automotive_android_manifest));
+ String carServicePackageName = SystemProperties.get("ro.android.car.carservice.package",
+ null);
+
+ assertWithMessage("Car service package not defined").that(
+ carServicePackageName).isNotNull();
+
+ declaredPermissionsMap.putAll(
+ getPermissionsForPackage(sContext, carServicePackageName));
+
+ // Load signature permission declared in CarService-builtin
+ String carServiceBuiltInPackageName = "com.android.car";
+ Map<String, PermissionInfo> carServiceBuiltInPermissionsMap = getPermissionsForPackage(
+ sContext, carServiceBuiltInPackageName);
+ // carServiceBuiltInPermissionsMap should only have signature permissions and those
+ // permissions should not be defined in car service updatable.
+ for (Map.Entry<String, PermissionInfo> permissionData : carServiceBuiltInPermissionsMap
+ .entrySet()) {
+ PermissionInfo carServiceBuiltInDeclaredPermission = permissionData.getValue();
+ String carServiceBuiltInDeclaredPermissionName = permissionData.getKey();
+
+ // Signature only permission should be defined in built-in car service
+ if ((carServiceBuiltInDeclaredPermission
+ .getProtection() != PermissionInfo.PROTECTION_SIGNATURE)
+ || (carServiceBuiltInDeclaredPermission.getProtectionFlags() != 0)) {
+ offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName
+ + " should be signature only permission to be declared in"
+ + " carServiceBuiltIn package.");
+ continue;
+ }
+
+ if (declaredPermissionsMap.get(carServiceBuiltInDeclaredPermissionName) != null) {
+ offendingList.add("Permission " + carServiceBuiltInDeclaredPermissionName
+ + " from car service builtin is already declared in other packages.");
+ continue;
+ }
+ }
+ declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap);
+ }
+
+ for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
+ String expectedPermissionName = expectedPermission.name;
+ if (shouldSkipPermission(expectedPermissionName)) {
+ // This permission doesn't need to exist yet, but will exist in
+ // a future SPL. It is acceptable to declare the permission
+ // even in an earlier SPL, so we remove it here so it doesn't
+ // trigger a failure after the loop.
+ declaredPermissionsMap.remove(expectedPermissionName);
+ continue;
+ }
+
+ // OEMs cannot remove permissions
+ PermissionInfo declaredPermission = declaredPermissionsMap.get(expectedPermissionName);
+ if (declaredPermission == null) {
+ offendingList.add("Permission " + expectedPermissionName + " must be declared");
+ continue;
+ }
+
+ // We want to end up with OEM defined permissions and groups to check their namespace
+ declaredPermissionsMap.remove(expectedPermissionName);
+
+ // OEMs cannot change permission protection
+ final int expectedProtection = expectedPermission.protectionLevel
+ & PROTECTION_MASK_BASE;
+ final int declaredProtection = declaredPermission.protectionLevel
+ & PROTECTION_MASK_BASE;
+ if (expectedProtection != declaredProtection) {
+ offendingList.add(
+ String.format(
+ "Permission %s invalid protection level %x, expected %x",
+ expectedPermissionName, declaredProtection, expectedProtection));
+ }
+
+ // OEMs cannot change permission flags
+ final int expectedFlags = expectedPermission.flags;
+ final int declaredFlags = (declaredPermission.flags & ~FLAG_INSTALLED);
+ if (expectedFlags != declaredFlags) {
+ offendingList.add(
+ String.format(
+ "Permission %s invalid flags %x, expected %x",
+ expectedPermissionName,
+ declaredFlags,
+ expectedFlags));
+ }
+
+ // OEMs cannot change permission protection flags
+ final int expectedProtectionFlags =
+ expectedPermission.protectionLevel & ~PROTECTION_MASK_BASE;
+ final int declaredProtectionFlags = declaredPermission.getProtectionFlags();
+ if (expectedProtectionFlags != declaredProtectionFlags) {
+ offendingList.add(
+ String.format(
+ "Permission %s invalid enforced protection %x, expected %x",
+ expectedPermissionName,
+ declaredProtectionFlags,
+ expectedProtectionFlags));
+ }
+
+ // OEMs cannot change permission grouping
+ if ((declaredPermission.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
+ if (!Objects.equals(expectedPermission.group, declaredPermission.group)) {
+ offendingList.add(
+ "Permission " + expectedPermissionName + " not in correct group "
+ + "(expected=" + expectedPermission.group + " actual="
+ + declaredPermission.group);
+ }
+
+ if (declaredPermission.group != null
+ && !declaredGroupsSet.contains(declaredPermission.group)) {
+ offendingList.add(
+ "Permission group " + expectedPermission.group + " must be defined");
+ }
+ }
+
+ // OEMs cannot change background permission mapping
+ if (!Objects.equals(expectedPermission.backgroundPermission,
+ declaredPermission.backgroundPermission)) {
+ offendingList.add(
+ String.format(
+ "Permission %s invalid background permission %s, expected %s",
+ expectedPermissionName,
+ declaredPermission.backgroundPermission,
+ expectedPermission.backgroundPermission));
+ }
+ }
+
+ // OEMs cannot define permissions in the platform namespace
+ for (String permission : declaredPermissionsMap.keySet()) {
+ if (permission.startsWith(PLATFORM_ROOT_NAMESPACE)) {
+ final PermissionInfo permInfo = declaredPermissionsMap.get(permission);
+ offendingList.add(
+ "Cannot define permission " + permission
+ + ", package " + permInfo.packageName
+ + " in android namespace");
+ }
+ }
+
+ // OEMs cannot define groups in the platform namespace
+ for (PermissionGroupInfo declaredGroup : declaredGroups) {
+ if (!expectedPermissionGroups.contains(declaredGroup.name)) {
+ if (declaredGroup.name != null) {
+ if (declaredGroup.packageName.equals(PLATFORM_PACKAGE_NAME)
+ && declaredGroup.name.startsWith(PLATFORM_ROOT_NAMESPACE)) {
+ offendingList.add(
+ "Cannot define group " + declaredGroup.name
+ + ", package " + declaredGroup.packageName
+ + " in android namespace");
+ }
+ }
+ }
+ }
+
+ // OEMs cannot define new ephemeral permissions
+ for (String permission : declaredPermissionsMap.keySet()) {
+ PermissionInfo info = declaredPermissionsMap.get(permission);
+ if ((info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0) {
+ offendingList.add("Cannot define new instant permission " + permission);
+ }
+ }
+
+ // Fail on any offending item
+ assertWithMessage("list of offending permissions").that(offendingList).isEmpty();
+ }
+
+ private boolean hasRevokeNotificationNoKillPermission(PackageInfo info) {
+ if (info.requestedPermissions == null) {
+ return false;
+ }
+
+ for (int i = 0; i < info.requestedPermissions.length; i++) {
+ if (Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL.equals(
+ info.requestedPermissions[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private List<ExpectedPermissionInfo> loadExpectedPermissions(int resourceId) throws Exception {
+ List<ExpectedPermissionInfo> permissions = new ArrayList<>();
+ try (InputStream in = sContext.getResources().openRawResource(resourceId)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ if (TAG_PERMISSION.equals(parser.getName())) {
+ ExpectedPermissionInfo permissionInfo = new ExpectedPermissionInfo(
+ parser.getAttributeValue(null, ATTR_NAME),
+ parser.getAttributeValue(null, ATTR_PERMISSION_GROUP),
+ parser.getAttributeValue(null, ATTR_BACKGROUND_PERMISSION),
+ parsePermissionFlags(
+ parser.getAttributeValue(null, ATTR_PERMISSION_FLAGS)),
+ parseProtectionLevel(
+ parser.getAttributeValue(null, ATTR_PROTECTION_LEVEL)));
+ permissions.add(permissionInfo);
+ } else {
+ Log.e(LOG_TAG, "Unknown tag " + parser.getName());
+ }
+ }
+ }
+
+ return permissions;
+ }
+
+ private Set<String> loadExpectedPermissionGroupNames(int resourceId) throws Exception {
+ ArraySet<String> permissionGroups = new ArraySet<>();
+ try (InputStream in = sContext.getResources().openRawResource(resourceId)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ if (TAG_PERMISSION_GROUP.equals(parser.getName())) {
+ permissionGroups.add(parser.getAttributeValue(null, ATTR_NAME));
+ } else {
+ Log.e(LOG_TAG, "Unknown tag " + parser.getName());
+ }
+ }
+ }
+ return permissionGroups;
+ }
+
+ private static int parsePermissionFlags(@Nullable String permissionFlagsString) {
+ if (permissionFlagsString == null) {
+ return 0;
+ }
+
+ int protectionFlags = 0;
+ String[] fragments = permissionFlagsString.split("\\|");
+ for (String fragment : fragments) {
+ switch (fragment.trim()) {
+ case "removed": {
+ protectionFlags |= PermissionInfo.FLAG_REMOVED;
+ } break;
+ case "costsMoney": {
+ protectionFlags |= PermissionInfo.FLAG_COSTS_MONEY;
+ } break;
+ case "hardRestricted": {
+ protectionFlags |= PermissionInfo.FLAG_HARD_RESTRICTED;
+ } break;
+ case "immutablyRestricted": {
+ protectionFlags |= PermissionInfo.FLAG_IMMUTABLY_RESTRICTED;
+ } break;
+ case "softRestricted": {
+ protectionFlags |= PermissionInfo.FLAG_SOFT_RESTRICTED;
+ } break;
+ }
+ }
+ return protectionFlags;
+ }
+
+ private static int parseProtectionLevel(String protectionLevelString) {
+ int protectionLevel = 0;
+ String[] fragments = protectionLevelString.split("\\|");
+ for (String fragment : fragments) {
+ switch (fragment.trim()) {
+ case "normal": {
+ protectionLevel |= PermissionInfo.PROTECTION_NORMAL;
+ } break;
+ case "dangerous": {
+ protectionLevel |= PermissionInfo.PROTECTION_DANGEROUS;
+ } break;
+ case "signature": {
+ protectionLevel |= PermissionInfo.PROTECTION_SIGNATURE;
+ } break;
+ case "signatureOrSystem": {
+ protectionLevel |= PermissionInfo.PROTECTION_SIGNATURE;
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM;
+ } break;
+ case "internal": {
+ protectionLevel |= PermissionInfo.PROTECTION_INTERNAL;
+ } break;
+ case "system": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM;
+ } break;
+ case "installer": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_INSTALLER;
+ } break;
+ case "verifier": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_VERIFIER;
+ } break;
+ case "preinstalled": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_PREINSTALLED;
+ } break;
+ case "pre23": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_PRE23;
+ } break;
+ case "appop": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_APPOP;
+ } break;
+ case "development": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_DEVELOPMENT;
+ } break;
+ case "privileged": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_PRIVILEGED;
+ } break;
+ case "oem": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_OEM;
+ } break;
+ case "vendorPrivileged": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED;
+ } break;
+ case "setup": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_SETUP;
+ } break;
+ case "textClassifier": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER;
+ } break;
+ case "configurator": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_CONFIGURATOR;
+ } break;
+ case "incidentReportApprover": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER;
+ } break;
+ case "appPredictor": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR;
+ } break;
+ case "instant": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_INSTANT;
+ } break;
+ case "runtime": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY;
+ } break;
+ case "companion": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_COMPANION;
+ } break;
+ case "retailDemo": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO;
+ } break;
+ case "recents": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_RECENTS;
+ } break;
+ case "role": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_ROLE;
+ } break;
+ case "knownSigner": {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER;
+ } break;
+ case "module" : {
+ protectionLevel |= PermissionInfo.PROTECTION_FLAG_MODULE;
+ } break;
+ }
+ }
+ return protectionLevel;
+ }
+
+ private static Map<String, PermissionInfo> getPermissionsForPackage(Context context, String pkg)
+ throws NameNotFoundException {
+ PackageInfo packageInfo = context.getPackageManager()
+ .getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
+ Map<String, PermissionInfo> declaredPermissionsMap = new ArrayMap<>();
+
+ for (PermissionInfo declaredPermission : packageInfo.permissions) {
+ declaredPermissionsMap.put(declaredPermission.name, declaredPermission);
+ }
+ return declaredPermissionsMap;
+ }
+
+ private static Date parseDate(String date) {
+ Date patchDate = new Date();
+ try {
+ SimpleDateFormat template = new SimpleDateFormat("yyyy-MM-dd");
+ patchDate = template.parse(date);
+ } catch (ParseException e) {
+ }
+
+ return patchDate;
+ }
+
+ private boolean shouldSkipPermission(String permissionName) {
+ switch (permissionName) {
+ case HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PERMISSION:
+ return parseDate(SECURITY_PATCH).before(HIDE_NON_SYSTEM_OVERLAY_WINDOWS_PATCH_DATE);
+ case MANAGE_COMPANION_DEVICES_PERMISSION:
+ return parseDate(SECURITY_PATCH).before(MANAGE_COMPANION_DEVICES_PATCH_DATE);
+ default:
+ return false;
+ }
+ }
+
+ private class ExpectedPermissionInfo {
+ final @NonNull String name;
+ final @Nullable String group;
+ final @Nullable String backgroundPermission;
+ final int flags;
+ final int protectionLevel;
+
+ private ExpectedPermissionInfo(@NonNull String name, @Nullable String group,
+ @Nullable String backgroundPermission, int flags, int protectionLevel) {
+ this.name = name;
+ this.group = group;
+ this.backgroundPermission = backgroundPermission;
+ this.flags = flags;
+ this.protectionLevel = protectionLevel;
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PrivappPermissionsTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PrivappPermissionsTest.java
new file mode 100644
index 000000000..f33e8a6e6
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/PrivappPermissionsTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2016 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.permissionpolicy.cts;
+
+import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
+import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+
+import static com.google.common.collect.Maps.filterValues;
+import static com.google.common.collect.Sets.difference;
+import static com.google.common.collect.Sets.intersection;
+import static com.google.common.collect.Sets.newHashSet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.AppModeFull;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.PropertyUtil;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Tests enforcement of signature|privileged permission whitelist:
+ * <ul>
+ * <li>Report what is granted into the CTS log
+ * <li>Ensure all priv permissions are exclusively granted to applications declared in
+ * &lt;privapp-permissions&gt;
+ * </ul>
+ */
+@AppModeFull(reason = "This test test platform properties, not capabilities of an apps")
+@RunWith(AndroidJUnit4.class)
+public class PrivappPermissionsTest {
+
+ private static final boolean DEBUG = false;
+
+ private static final String TAG = "PrivappPermissionsTest";
+
+ private static final String PLATFORM_PACKAGE_NAME = "android";
+
+ @Test
+ public void privappPermissionsMustBeEnforced() {
+ assertEquals("ro.control_privapp_permissions is not set to enforce",
+ "enforce", PropertyUtil.getProperty("ro.control_privapp_permissions"));
+ }
+
+ @Test
+ public void privappPermissionsNeedToBeWhitelisted() throws Exception {
+ Set<String> platformPrivPermissions = new HashSet<>();
+ PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ PackageInfo platformPackage = pm.getPackageInfo(PLATFORM_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS);
+
+ for (PermissionInfo permission : platformPackage.permissions) {
+ int protectionLevel = permission.protectionLevel;
+ if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
+ platformPrivPermissions.add(permission.name);
+ }
+ }
+
+ List<PackageInfo> installedPackages = pm
+ .getInstalledPackages(MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS);
+ installedPackages.sort(Comparator.comparing(p -> p.packageName));
+
+ Map<String, Set<String>> packagesGrantedNotInWhitelist = new HashMap<>();
+ Map<String, Set<String>> packagesNotGrantedNotRemovedNotInDenylist = new HashMap<>();
+ for (PackageInfo pkg : installedPackages) {
+ String packageName = pkg.packageName;
+ if (!pkg.applicationInfo.isPrivilegedApp()
+ || PLATFORM_PACKAGE_NAME.equals(packageName)) {
+ continue;
+ }
+
+ PackageInfo factoryPkg = pm
+ .getPackageInfo(packageName, MATCH_FACTORY_ONLY | GET_PERMISSIONS
+ | MATCH_UNINSTALLED_PACKAGES);
+
+ assertNotNull("No system image version found for " + packageName, factoryPkg);
+
+ Set<String> factoryRequestedPrivPermissions;
+ if (factoryPkg.requestedPermissions == null) {
+ factoryRequestedPrivPermissions = Collections.emptySet();
+ } else {
+ factoryRequestedPrivPermissions = intersection(
+ newHashSet(factoryPkg.requestedPermissions), platformPrivPermissions);
+ }
+
+ Map<String, Boolean> requestedPrivPermissions = new ArrayMap<>();
+ if (pkg.requestedPermissions != null) {
+ for (int i = 0; i < pkg.requestedPermissions.length; i++) {
+ String permission = pkg.requestedPermissions[i];
+ if (platformPrivPermissions.contains(permission)) {
+ requestedPrivPermissions.put(permission,
+ (pkg.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED)
+ != 0);
+ }
+ }
+ }
+
+ // If an app is requesting any privileged permissions, log the details and verify
+ // that granted permissions are whitelisted
+ if (!factoryRequestedPrivPermissions.isEmpty() && !requestedPrivPermissions.isEmpty()) {
+ Set<String> granted = filterValues(requestedPrivPermissions,
+ isGranted -> isGranted).keySet();
+
+ Set<String> factoryNotGranted = difference(factoryRequestedPrivPermissions,
+ granted);
+
+ // priv permissions that the system package requested, but the current package not
+ // anymore
+ Set<String> removed = difference(factoryRequestedPrivPermissions,
+ requestedPrivPermissions.keySet());
+
+ Set<String> whitelist = getPrivAppPermissions(packageName);
+ Set<String> denylist = getPrivAppDenyPermissions(packageName);
+
+ if (DEBUG) {
+ String msg = "Application " + packageName + "\n"
+ + " Factory requested permissions:\n"
+ + getPrintableSet(" ", factoryRequestedPrivPermissions)
+ + " Granted:\n"
+ + getPrintableSet(" ", granted)
+ + " Removed:\n"
+ + getPrintableSet(" ", removed)
+ + " Whitelisted:\n"
+ + getPrintableSet(" ", whitelist)
+ + " Denylisted:\n"
+ + getPrintableSet(" ", denylist)
+ + " Factory not granted:\n"
+ + getPrintableSet(" ", factoryNotGranted);
+
+ for (String line : msg.split("\n")) {
+ Log.i(TAG, line);
+
+ // Prevent log from truncating output
+ Thread.sleep(10);
+ }
+ }
+
+ Set<String> grantedNotInWhitelist = difference(granted, whitelist);
+ Set<String> factoryNotGrantedNotRemovedNotInDenylist = difference(difference(
+ factoryNotGranted, removed), denylist);
+
+ if (!grantedNotInWhitelist.isEmpty()) {
+ packagesGrantedNotInWhitelist.put(packageName, grantedNotInWhitelist);
+ }
+
+ if (!factoryNotGrantedNotRemovedNotInDenylist.isEmpty()) {
+ packagesNotGrantedNotRemovedNotInDenylist.put(packageName,
+ factoryNotGrantedNotRemovedNotInDenylist);
+ }
+ }
+ }
+ StringBuilder message = new StringBuilder();
+ if (!packagesGrantedNotInWhitelist.isEmpty()) {
+ message.append("Not whitelisted permissions are granted: "
+ + packagesGrantedNotInWhitelist.toString());
+ }
+ if (!packagesNotGrantedNotRemovedNotInDenylist.isEmpty()) {
+ if (message.length() != 0) {
+ message.append(", ");
+ }
+ message.append("Requested permissions not granted: "
+ + packagesNotGrantedNotRemovedNotInDenylist.toString());
+ }
+ if (!packagesGrantedNotInWhitelist.isEmpty()
+ || !packagesNotGrantedNotRemovedNotInDenylist.isEmpty()) {
+ fail(message.toString());
+ }
+ }
+
+ private <T> String getPrintableSet(String indendation, Set<T> set) {
+ if (set.isEmpty()) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ for (T e : new TreeSet<>(set)) {
+ if (!TextUtils.isEmpty(e.toString().trim())) {
+ sb.append(indendation);
+ sb.append(e);
+ sb.append("\n");
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private Set<String> getPrivAppPermissions(String packageName) throws IOException {
+ String output = SystemUtil.runShellCommand(
+ InstrumentationRegistry.getInstrumentation(),
+ "cmd package get-privapp-permissions " + packageName).trim();
+ if (output.startsWith("{") && output.endsWith("}")) {
+ String[] split = output.substring(1, output.length() - 1).split("\\s*,\\s*");
+ return new LinkedHashSet<>(Arrays.asList(split));
+ }
+ return Collections.emptySet();
+ }
+
+ private Set<String> getPrivAppDenyPermissions(String packageName) throws IOException {
+ String output = SystemUtil.runShellCommand(
+ InstrumentationRegistry.getInstrumentation(),
+ "cmd package get-privapp-deny-permissions " + packageName).trim();
+ if (output.startsWith("{") && output.endsWith("}")) {
+ String[] split = output.substring(1, output.length() - 1).split("\\s*,\\s*");
+ return new LinkedHashSet<>(Arrays.asList(split));
+ }
+ return Collections.emptySet();
+ }
+
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ProtectedBroadcastsTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ProtectedBroadcastsTest.java
new file mode 100644
index 000000000..71c990441
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/ProtectedBroadcastsTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 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.permissionpolicy.cts;
+
+import android.content.Intent;
+import android.content.RestrictionsManager;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+
+/**
+ * Verify that applications can not send protected broadcasts.
+ */
+public class ProtectedBroadcastsTest extends AndroidTestCase {
+ private static final String BROADCASTS[] = new String[] {
+ Intent.ACTION_SCREEN_OFF,
+ Intent.ACTION_SCREEN_ON,
+ Intent.ACTION_USER_PRESENT,
+ Intent.ACTION_TIME_TICK,
+ Intent.ACTION_TIMEZONE_CHANGED,
+ Intent.ACTION_BOOT_COMPLETED,
+ Intent.ACTION_PACKAGE_INSTALL,
+ Intent.ACTION_PACKAGE_ADDED,
+ Intent.ACTION_PACKAGE_REPLACED,
+ Intent.ACTION_PACKAGE_REMOVED,
+ Intent.ACTION_PACKAGE_CHANGED,
+ Intent.ACTION_PACKAGE_RESTARTED,
+ Intent.ACTION_PACKAGE_DATA_CLEARED,
+ Intent.ACTION_UID_REMOVED,
+ Intent.ACTION_CONFIGURATION_CHANGED,
+ Intent.ACTION_BATTERY_CHANGED,
+ Intent.ACTION_BATTERY_LOW,
+ Intent.ACTION_BATTERY_OKAY,
+ Intent.ACTION_POWER_CONNECTED,
+ Intent.ACTION_POWER_DISCONNECTED,
+ Intent.ACTION_SHUTDOWN,
+ Intent.ACTION_DEVICE_STORAGE_LOW,
+ Intent.ACTION_DEVICE_STORAGE_OK,
+ Intent.ACTION_REBOOT,
+ "com.android.server.WifiManager.action.START_SCAN",
+ "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP",
+ "android.net.wifi.WIFI_STATE_CHANGED",
+ "android.net.wifi.WIFI_AP_STATE_CHANGED",
+ "android.net.wifi.SCAN_RESULTS",
+ "android.net.wifi.RSSI_CHANGED",
+ "android.net.wifi.STATE_CHANGE",
+ "android.net.wifi.LINK_CONFIGURATION_CHANGED",
+ "android.net.wifi.CONFIGURED_NETWORKS_CHANGE",
+ "android.net.wifi.supplicant.CONNECTION_CHANGE",
+ "android.net.wifi.supplicant.STATE_CHANGE",
+ "android.net.wifi.p2p.STATE_CHANGED",
+ "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE",
+ "android.net.wifi.p2p.THIS_DEVICE_CHANGED",
+ "android.net.wifi.p2p.PEERS_CHANGED",
+ "android.net.wifi.p2p.CONNECTION_STATE_CHANGE",
+ "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED",
+ "android.net.conn.TETHER_STATE_CHANGED",
+ "android.net.conn.INET_CONDITION_ACTION",
+ "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED",
+ RestrictionsManager.ACTION_PERMISSION_RESPONSE_RECEIVED,
+ RestrictionsManager.ACTION_REQUEST_PERMISSION
+ };
+
+ private static final String BROADCASTS_TELEPHONY[] = new String[] {
+ Intent.ACTION_NEW_OUTGOING_CALL,
+ "android.intent.action.SERVICE_STATE",
+ "android.intent.action.SIG_STR",
+ "android.intent.action.RADIO_TECHNOLOGY",
+ "android.intent.action.ANY_DATA_STATE",
+ "android.intent.action.ACTION_MDN_STATE_CHANGED",
+ "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED",
+ "android.intent.action.SIM_STATE_CHANGED",
+ "android.telephony.action.SERVICE_PROVIDERS_UPDATED",
+ "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED",
+ "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED",
+ "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS",
+ };
+
+ /**
+ * Verify that protected broadcast actions can't be sent.
+ */
+ public void testSendProtectedBroadcasts() {
+ for (String action : BROADCASTS) {
+ try {
+ Intent intent = new Intent(action);
+ getContext().sendBroadcast(intent);
+ fail("expected security exception broadcasting action: " + action);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+ }
+ }
+
+ public void testSendProtectedTelephonyBroadcasts() {
+ if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+ for (String action : BROADCASTS_TELEPHONY) {
+ try {
+ Intent intent = new Intent(action);
+ getContext().sendBroadcast(intent);
+ fail("expected security exception broadcasting telephony action: " + action);
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ }
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedPermissionsTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedPermissionsTest.java
new file mode 100644
index 000000000..5f396c49c
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedPermissionsTest.java
@@ -0,0 +1,745 @@
+/*
+ * Copyright (C) 2019 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 andf
+ * limitations under the License.
+ */
+
+package android.permissionpolicy.cts;
+
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
+import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.READ_SMS;
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permission.cts.PermissionUtils.isPermissionGranted;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.Manifest.permission;
+import android.app.AppOpsManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.Session;
+import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.SystemUserOnly;
+import android.util.ArraySet;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.FlakyTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ThrowingRunnable;
+import com.android.modules.utils.build.SdkLevel;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+/**
+ * Tests for restricted permission behaviors.
+ */
+public class RestrictedPermissionsTest {
+ private static final String APK_USES_LOCATION_22 =
+ "/data/local/tmp/cts-permissionpolicy/CtsLocationPermissionsUserSdk22.apk";
+
+ private static final String APK_USES_LOCATION_29 =
+ "/data/local/tmp/cts-permissionpolicy/CtsLocationPermissionsUserSdk29.apk";
+
+ private static final String APK_USES_SMS_CALL_LOG_22 =
+ "/data/local/tmp/cts-permissionpolicy/CtsSMSCallLogPermissionsUserSdk22.apk";
+
+ private static final String APK_NAME_USES_SMS_CALL_LOG_29 =
+ "CtsSMSCallLogPermissionsUserSdk29.apk";
+
+ private static final String APK_USES_SMS_CALL_LOG_29 =
+ "/data/local/tmp/cts-permissionpolicy/CtsSMSCallLogPermissionsUserSdk29.apk";
+
+ private static final String APK_USES_STORAGE_DEFAULT_29 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk29.apk";
+
+ private static final String PKG = "android.permissionpolicy.cts.restrictedpermissionuser";
+
+ private static final String APK_USES_SMS_RESTRICTED_SHARED_UID =
+ "/data/local/tmp/cts-permissionpolicy/CtsSMSRestrictedWithSharedUid.apk";
+
+ private static final String PKG_USES_SMS_RESTRICTED_SHARED_UID =
+ "android.permissionpolicy.cts.smswithshareduid.restricted";
+
+ private static final String APK_USES_SMS_NOT_RESTRICTED_SHARED_UID =
+ "/data/local/tmp/cts-permissionpolicy/CtsSMSNotRestrictedWithSharedUid.apk";
+
+ private static final String PKG_USES_SMS_NOT_RESTRICTED_SHARED_UID =
+ "android.permissionpolicy.cts.smswithshareduid.notrestricted";
+
+ private static final long UI_TIMEOUT = 5000L;
+
+ private static @NonNull BroadcastReceiver sCommandReceiver;
+
+ @BeforeClass
+ public static void setUpOnce() {
+ sCommandReceiver = new CommandBroadcastReceiver();
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction("installRestrictedPermissionUserApp");
+ intentFilter.addAction("uninstallApp");
+ getContext().registerReceiver(sCommandReceiver, intentFilter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
+ }
+
+ @AfterClass
+ public static void tearDownOnce() {
+ getContext().unregisterReceiver(sCommandReceiver);
+ }
+
+ @Test
+ @AppModeFull
+ public void testDefaultAllRestrictedPermissionsWhitelistedAtInstall29() throws Exception {
+ // Install with no changes to whitelisted permissions, not attempting to grant.
+ installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
+ Collections.EMPTY_SET /*grantedPermissions*/);
+
+ // All restricted permission should be whitelisted.
+ assertAllRestrictedPermissionWhitelisted();
+
+ // No restricted permission should be granted.
+ assertNoRestrictedPermissionGranted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testSomeRestrictedPermissionsWhitelistedAtInstall29() throws Exception {
+ // Whitelist only these permissions.
+ final Set<String> whitelistedPermissions = new ArraySet<>(2);
+ whitelistedPermissions.add(Manifest.permission.SEND_SMS);
+ whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
+
+ // Install with some whitelisted permissions, not attempting to grant.
+ installRestrictedPermissionUserApp(whitelistedPermissions,
+ Collections.EMPTY_SET /*grantedPermissions*/);
+
+ // Some restricted permission should be whitelisted.
+ assertRestrictedPermissionWhitelisted(whitelistedPermissions);
+
+ // No restricted permission should be granted.
+ assertNoRestrictedPermissionGranted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testNoneRestrictedPermissionWhitelistedAtInstall29() throws Exception {
+ // Install with all whitelisted permissions, not attempting to grant.
+ installRestrictedPermissionUserApp(Collections.emptySet(),
+ Collections.EMPTY_SET /*grantedPermissions*/);
+
+ // No restricted permission should be whitelisted.
+ assertNoRestrictedPermissionWhitelisted();
+
+ // No restricted permission should be granted.
+ assertNoRestrictedPermissionGranted();
+ }
+
+ @Test
+ @AppModeFull
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_SMS user restriction")
+ public void testDefaultAllRestrictedPermissionsWhitelistedAtInstall22() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_SMS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ String bypassLowTargetSdkFlag = "";
+ if (SdkLevel.isAtLeastU()) {
+ bypassLowTargetSdkFlag = " --bypass-low-target-sdk-block";
+ }
+
+ // Install with no changes to whitelisted permissions
+ runShellCommandOrThrow("pm install" + bypassLowTargetSdkFlag
+ + " -g --force-queryable " + APK_USES_SMS_CALL_LOG_22);
+
+ // All restricted permission should be whitelisted.
+ assertAllRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void testSomeRestrictedPermissionsWhitelistedAtInstall22() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ // Whitelist only these permissions.
+ final Set<String> whitelistedPermissions = new ArraySet<>(2);
+ whitelistedPermissions.add(Manifest.permission.SEND_SMS);
+ whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
+
+ // Install with some whitelisted permissions
+ installApp(APK_USES_SMS_CALL_LOG_22, whitelistedPermissions, null /*grantedPermissions*/);
+
+ // Some restricted permission should be whitelisted.
+ assertRestrictedPermissionWhitelisted(whitelistedPermissions);
+ }
+
+ @Test
+ @AppModeFull
+ public void testNoneRestrictedPermissionWhitelistedAtInstall22() throws Exception {
+ // Install with all whitelisted permissions
+ installApp(APK_USES_SMS_CALL_LOG_22, Collections.emptySet(),
+ null /*grantedPermissions*/);
+
+ // No restricted permission should be whitelisted.
+ assertNoRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testLocationBackgroundPermissionWhitelistedAtInstall29() throws Exception {
+ installApp(APK_USES_LOCATION_29, null, new ArraySet<>(Arrays.asList(ACCESS_FINE_LOCATION,
+ ACCESS_BACKGROUND_LOCATION)));
+ assertAllRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testLocationBackgroundPermissionNotWhitelistedAtInstall29() throws Exception {
+ installApp(APK_USES_LOCATION_29, Collections.emptySet(),
+ Collections.singleton(ACCESS_FINE_LOCATION));
+ assertNoRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testLocationBackgroundPermissionWhitelistedAtInstall22() throws Exception {
+ installApp(APK_USES_LOCATION_22, null, new ArraySet<>(Arrays.asList(ACCESS_FINE_LOCATION,
+ ACCESS_BACKGROUND_LOCATION)));
+ assertAllRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testLocationBackgroundPermissionNotWhitelistedAtInstall22() throws Exception {
+ installApp(APK_USES_LOCATION_22, Collections.emptySet(),
+ Collections.singleton(ACCESS_FINE_LOCATION));
+ assertNoRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_OUTGOING_CALLS user restriction")
+ public void testSomeRestrictedPermissionsGrantedAtInstall() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_OUTGOING_CALLS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ // Grant only these permissions.
+ final Set<String> grantedPermissions = new ArraySet<>(1);
+ grantedPermissions.add(Manifest.permission.SEND_SMS);
+ grantedPermissions.add(Manifest.permission.READ_CALL_LOG);
+
+ // Install with no whitelisted permissions attempting to grant.
+ installRestrictedPermissionUserApp(null /*whitelistedPermissions*/, grantedPermissions);
+
+ // All restricted permission should be whitelisted.
+ assertAllRestrictedPermissionWhitelisted();
+
+ // Some restricted permission should be granted.
+ assertRestrictedPermissionGranted(grantedPermissions);
+ }
+
+ @Test
+ @AppModeFull
+ public void testCanGrantSoftRestrictedNotWhitelistedPermissions() throws Exception {
+ try {
+ final Set<String> grantedPermissions = new ArraySet<>();
+ grantedPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ grantedPermissions.add(permission.WRITE_EXTERNAL_STORAGE);
+
+ installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet(), grantedPermissions);
+
+ assertRestrictedPermissionGranted(grantedPermissions);
+ } finally {
+ uninstallApp();
+ }
+ }
+
+ @Test
+ @AppModeFull
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_SMS user restriction")
+ public void testAllRestrictedPermissionsGrantedAtInstall() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_SMS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ // Install with whitelisted permissions attempting to grant.
+ installRestrictedPermissionUserApp(null /*whitelistedPermissions*/,
+ null);
+
+ // All restricted permission should be whitelisted.
+ assertAllRestrictedPermissionWhitelisted();
+
+ // Some restricted permission should be granted.
+ assertAllRestrictedPermissionGranted();
+ }
+
+ @Test
+ @AppModeFull
+ public void testWhitelistAccessControl() throws Exception {
+ // Install with no whitelisted permissions not attempting to grant.
+ installRestrictedPermissionUserApp(Collections.emptySet(), null);
+
+ assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM);
+
+ assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);
+
+ assertWeCannotReadOrWriteWhileShellCanReadAndWrite(
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ }
+
+ @Test
+ @AppModeFull
+ public void onSideLoadRestrictedPermissionsWhitelistingDefault() throws Exception {
+ installRestrictedPermissionUserApp(new SessionParams(SessionParams.MODE_FULL_INSTALL));
+
+ // All restricted permissions whitelisted on side-load by default
+ assertAllRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ public void onSideLoadAllRestrictedPermissionsWhitelisted() throws Exception {
+ SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+ params.setWhitelistedRestrictedPermissions(SessionParams.RESTRICTED_PERMISSIONS_ALL);
+
+ installRestrictedPermissionUserApp(params);
+
+ assertAllRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ @FlakyTest
+ public void onSideLoadWhitelistSomePermissions() throws Exception {
+ Set<String> whitelistedPermissions = new ArraySet<>();
+ whitelistedPermissions.add(Manifest.permission.SEND_SMS);
+ whitelistedPermissions.add(Manifest.permission.READ_CALL_LOG);
+
+ SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+ params.setWhitelistedRestrictedPermissions(whitelistedPermissions);
+
+ installRestrictedPermissionUserApp(params);
+
+ assertRestrictedPermissionWhitelisted(whitelistedPermissions);
+ }
+
+ @Test
+ @AppModeFull
+ @FlakyTest
+ public void onSideLoadWhitelistNoPermissions() throws Exception {
+ SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
+ params.setWhitelistedRestrictedPermissions(Collections.emptySet());
+
+ installRestrictedPermissionUserApp(params);
+
+ assertNoRestrictedPermissionWhitelisted();
+ }
+
+ @Test
+ @AppModeFull
+ @SystemUserOnly(reason = "Secondary users have the DISALLOW_SMS user restriction")
+ public void shareUidBetweenRestrictedAndNotRestrictedApp() throws Exception {
+ Assume.assumeTrue("Secondary users have the DISALLOW_SMS user restriction",
+ UserHandle.SYSTEM.equals(Process.myUserHandle()));
+
+ runShellCommandOrThrow(
+ "pm install -g --force-queryable --restrict-permissions "
+ + APK_USES_SMS_RESTRICTED_SHARED_UID);
+ runShellCommandOrThrow("pm install -g --force-queryable "
+ + APK_USES_SMS_NOT_RESTRICTED_SHARED_UID);
+
+ eventually(
+ () -> assertThat(isGranted(PKG_USES_SMS_RESTRICTED_SHARED_UID, READ_SMS)).isTrue());
+ // The apps share a UID, hence the whitelisting is shared too
+ assertThat(isGranted(PKG_USES_SMS_NOT_RESTRICTED_SHARED_UID, READ_SMS)).isTrue();
+ }
+
+ private static void installRestrictedPermissionUserApp(@NonNull SessionParams params)
+ throws Exception {
+ final CountDownLatch installLatch = new CountDownLatch(1);
+
+ // Create an install result receiver.
+ final BroadcastReceiver installReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE_INVALID)
+ == PackageInstaller.STATUS_SUCCESS) {
+ installLatch.countDown();
+ }
+ }
+ };
+
+ // Register the result receiver.
+ final String action = "android.permissionpolicy.cts.ACTION_INSTALL_COMMIT";
+ final IntentFilter intentFilter = new IntentFilter(action);
+ getContext().registerReceiver(installReceiver, intentFilter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
+
+ try {
+ // Create a session.
+ final PackageInstaller packageInstaller = getContext()
+ .getPackageManager().getPackageInstaller();
+ final int sessionId = packageInstaller.createSession(params);
+ final Session session = packageInstaller.openSession(sessionId);
+
+ // Write the apk.
+ try (
+ InputStream in = new BufferedInputStream(new FileInputStream(
+ new File(APK_USES_SMS_CALL_LOG_29)));
+ OutputStream out = session.openWrite(
+ APK_NAME_USES_SMS_CALL_LOG_29, 0, -1);
+ ) {
+ final byte[] buf = new byte[8192];
+ int size;
+ while ((size = in.read(buf)) != -1) {
+ out.write(buf, 0, size);
+ }
+ }
+
+ final Intent intent = new Intent(action);
+ intent.setPackage("android.permissionpolicy.cts");
+ final IntentSender intentSender = PendingIntent.getBroadcast(getContext(),
+ 1, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE)
+ .getIntentSender();
+
+ // Commit as shell to avoid confirm UI
+ runWithShellPermissionIdentity(() -> {
+ session.commit(intentSender);
+ installLatch.await(UI_TIMEOUT, TimeUnit.MILLISECONDS);
+ });
+ } finally {
+ getContext().unregisterReceiver(installReceiver);
+ }
+ }
+
+ private void assertWeCannotReadOrWriteWhileShellCanReadAndWrite(int whitelist)
+ throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ try {
+ packageManager.getWhitelistedRestrictedPermissions(PKG, whitelist);
+ fail();
+ } catch (SecurityException expected) {
+ /*ignore*/
+ }
+ try {
+ packageManager.addWhitelistedRestrictedPermission(PKG,
+ permission.SEND_SMS, whitelist);
+ fail();
+ } catch (SecurityException expected) {
+ /*ignore*/
+ }
+ runWithShellPermissionIdentity(() -> {
+ packageManager.addWhitelistedRestrictedPermission(PKG,
+ permission.SEND_SMS, whitelist);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ whitelist)).contains(permission.SEND_SMS);
+ packageManager.removeWhitelistedRestrictedPermission(PKG,
+ permission.SEND_SMS, whitelist);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ whitelist)).doesNotContain(permission.SEND_SMS);
+ });
+ }
+
+ private @NonNull Set<String> getPermissionsOfAppWithAnyOfFlags(int flags) throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final Set<String> restrictedPermissions = new ArraySet<>();
+ for (String permission : getRequestedPermissionsOfApp()) {
+ PermissionInfo permInfo = packageManager.getPermissionInfo(permission, 0);
+
+ if ((permInfo.flags & flags) != 0) {
+ restrictedPermissions.add(permission);
+ }
+ }
+ return restrictedPermissions;
+ }
+
+ private @NonNull Set<String> getRestrictedPermissionsOfApp() throws Exception {
+ return getPermissionsOfAppWithAnyOfFlags(
+ PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED);
+ }
+
+ private @NonNull String[] getRequestedPermissionsOfApp() throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final PackageInfo packageInfo = packageManager.getPackageInfo(PKG,
+ PackageManager.GET_PERMISSIONS);
+ return packageInfo.requestedPermissions;
+ }
+
+ private void assertAllRestrictedPermissionWhitelisted() throws Exception {
+ assertRestrictedPermissionWhitelisted(getRestrictedPermissionsOfApp());
+ }
+
+ private void assertNoRestrictedPermissionWhitelisted() throws Exception {
+ assertRestrictedPermissionWhitelisted(
+ Collections.EMPTY_SET /*expectedWhitelistedPermissions*/);
+ }
+
+ /**
+ * Assert that the passed in restrictions are whitelisted and that their app-op is set
+ * correctly.
+ *
+ * @param expectedWhitelistedPermissions The expected white listed permissions
+ */
+ private void assertRestrictedPermissionWhitelisted(
+ @NonNull Set<String> expectedWhitelistedPermissions) throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ eventually(() -> runWithShellPermissionIdentity(() -> {
+ final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final PackageInfo packageInfo = packageManager.getPackageInfo(PKG,
+ PackageManager.GET_PERMISSIONS);
+
+ final Set<String> whitelistedPermissions = packageManager
+ .getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
+ | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE);
+
+ assertThat(whitelistedPermissions).isNotNull();
+ assertWithMessage("Whitelisted permissions").that(whitelistedPermissions)
+ .containsExactlyElementsIn(expectedWhitelistedPermissions);
+
+ // Also assert that apps ops are properly set
+ for (String permission : getRestrictedPermissionsOfApp()) {
+ String op = AppOpsManager.permissionToOp(permission);
+ ArraySet<Integer> possibleModes = new ArraySet<>();
+
+ if (permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
+ op = AppOpsManager.OPSTR_FINE_LOCATION;
+
+ // If permission is denied app-op might be allowed/fg or ignored. It does
+ // not matter. If permission is granted, it has to be allowed/fg.
+ if (isPermissionGranted(PKG, Manifest.permission.ACCESS_FINE_LOCATION)) {
+ if (expectedWhitelistedPermissions.contains(permission)
+ && isPermissionGranted(PKG, permission)) {
+ possibleModes.add(AppOpsManager.MODE_ALLOWED);
+ } else {
+ possibleModes.add(AppOpsManager.MODE_FOREGROUND);
+ }
+ } else {
+ possibleModes.add(AppOpsManager.MODE_IGNORED);
+ possibleModes.add(AppOpsManager.MODE_ALLOWED);
+ possibleModes.add(AppOpsManager.MODE_FOREGROUND);
+ }
+ } else {
+ if (expectedWhitelistedPermissions.contains(permission)) {
+ // If permission is denied app-op might be allowed or ignored. It does not
+ // matter. If permission is granted, it has to be allowed.
+ possibleModes.add(AppOpsManager.MODE_ALLOWED);
+ if (!isPermissionGranted(PKG, permission)) {
+ possibleModes.add(AppOpsManager.MODE_IGNORED);
+ }
+ } else {
+ possibleModes.add(AppOpsManager.MODE_IGNORED);
+ }
+ }
+
+ assertWithMessage(op).that(appOpsManager.unsafeCheckOpRawNoThrow(op,
+ packageInfo.applicationInfo.uid, PKG)).isIn(possibleModes);
+ }
+ }));
+ }
+
+ private void assertAllRestrictedPermissionGranted() throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final PackageInfo packageInfo = packageManager.getPackageInfo(
+ PKG, PackageManager.GET_PERMISSIONS);
+ if (packageInfo.requestedPermissions != null) {
+ final int permissionCount = packageInfo.requestedPermissions.length;
+ for (int i = 0; i < permissionCount; i++) {
+ final String permission = packageInfo.requestedPermissions[i];
+ final PermissionInfo permissionInfo = packageManager.getPermissionInfo(
+ permission, 0);
+ if ((permissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0) {
+ assertThat((packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isNotEqualTo(0);
+ }
+ }
+ }
+ }
+
+ private void assertNoRestrictedPermissionGranted() throws Exception {
+ assertRestrictedPermissionGranted(Collections.EMPTY_SET);
+ }
+
+ private void assertRestrictedPermissionGranted(@NonNull Set<String> expectedGrantedPermissions)
+ throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final PackageInfo packageInfo = packageManager.getPackageInfo(
+ PKG, PackageManager.GET_PERMISSIONS);
+ if (packageInfo.requestedPermissions != null) {
+ final int permissionCount = packageInfo.requestedPermissions.length;
+ for (int i = 0; i < permissionCount; i++) {
+ final String permission = packageInfo.requestedPermissions[i];
+ final PermissionInfo permissionInfo = packageManager.getPermissionInfo(
+ permission, 0);
+ if ((permissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
+ || (permissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
+ if (expectedGrantedPermissions.contains(permission)) {
+ assertThat((packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isNotEqualTo(0);
+ } else {
+ assertThat((packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED)).isEqualTo(0);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Install {@link #APK_USES_SMS_CALL_LOG_29}.
+ *
+ * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
+ * @param grantedPermissions The permission to be granted. {@code null} == all
+ */
+ private void installRestrictedPermissionUserApp(@Nullable Set<String> whitelistedPermissions,
+ @Nullable Set<String> grantedPermissions) throws Exception {
+ installApp(APK_USES_SMS_CALL_LOG_29, whitelistedPermissions, grantedPermissions);
+ }
+
+ /**
+ * Install app and grant all permission.
+ *
+ * @param app The app to be installed
+ * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
+ */
+ private void installApp(@NonNull String app, @Nullable Set<String> whitelistedPermissions)
+ throws Exception {
+ installApp(app, whitelistedPermissions, null /*grantedPermissions*/);
+ }
+
+ /**
+ * Install an app.
+ *
+ * @param app The app to be installed
+ * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
+ * @param grantedPermissions The permission to be granted. {@code null} == all
+ */
+ private void installApp(@NonNull String app, @Nullable Set<String> whitelistedPermissions,
+ @Nullable Set<String> grantedPermissions) throws Exception {
+ String bypassLowTargetSdkFlag = "";
+ if (SdkLevel.isAtLeastU()) {
+ bypassLowTargetSdkFlag = " --bypass-low-target-sdk-block";
+ }
+
+ // Install the app and whitelist/grant all permission if requested.
+ String installResult = runShellCommandOrThrow("pm install -r --force-queryable"
+ + bypassLowTargetSdkFlag + " --restrict-permissions " + app);
+ assertThat(installResult.trim()).isEqualTo("Success");
+
+ final Set<String> adjustedWhitelistedPermissions;
+ if (whitelistedPermissions == null) {
+ adjustedWhitelistedPermissions = getRestrictedPermissionsOfApp();
+ } else {
+ adjustedWhitelistedPermissions = whitelistedPermissions;
+ }
+
+ final Set<String> adjustedGrantedPermissions;
+ if (grantedPermissions == null) {
+ adjustedGrantedPermissions = getRestrictedPermissionsOfApp();
+ } else {
+ adjustedGrantedPermissions = grantedPermissions;
+ }
+
+ // Whitelist subset of permissions if requested
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : adjustedWhitelistedPermissions) {
+ packageManager.addWhitelistedRestrictedPermission(PKG, permission,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ }
+ });
+
+ // Grant subset of permissions if requested
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : adjustedGrantedPermissions) {
+ packageManager.grantRuntimePermission(PKG, permission,
+ getContext().getUser());
+ packageManager.updatePermissionFlags(permission, PKG,
+ PackageManager.FLAG_PERMISSION_REVOKED_COMPAT, 0, getContext().getUser());
+ }
+ });
+
+ // Mark all permissions as reviewed as for pre-22 apps the restriction state might not be
+ // applied until reviewed
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : getRequestedPermissionsOfApp()) {
+ packageManager.updatePermissionFlags(permission, PKG,
+ PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0,
+ getContext().getUser());
+ }
+ });
+ }
+
+ @After
+ public void uninstallApp() {
+ runShellCommand("pm uninstall " + PKG);
+ runShellCommand("pm uninstall " + PKG_USES_SMS_NOT_RESTRICTED_SHARED_UID);
+ runShellCommand("pm uninstall " + PKG_USES_SMS_RESTRICTED_SHARED_UID);
+ }
+
+ private static @NonNull Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getContext();
+ }
+
+ private static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable command)
+ throws Exception {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity();
+ try {
+ command.run();
+ } finally {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionSharedUidTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionSharedUidTest.java
new file mode 100644
index 000000000..d6ee7a66b
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionSharedUidTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2019 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.permissionpolicy.cts;
+
+import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OPSTR_LEGACY_STORAGE;
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permissionpolicy.cts.RestrictedStoragePermissionSharedUidTest.StorageState.DENIED;
+import static android.permissionpolicy.cts.RestrictedStoragePermissionSharedUidTest.StorageState.ISOLATED;
+import static android.permissionpolicy.cts.RestrictedStoragePermissionSharedUidTest.StorageState.NON_ISOLATED;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static java.lang.Integer.min;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.ArrayList;
+
+@AppModeFull(reason = "Instant apps cannot access other app's properties")
+@RunWith(Parameterized.class)
+public class RestrictedStoragePermissionSharedUidTest {
+ private static final String LOG_TAG =
+ RestrictedStoragePermissionSharedUidTest.class.getSimpleName();
+
+ public enum StorageState {
+ /** The app has non-isolated storage */
+ NON_ISOLATED,
+
+ /** The app has isolated storage */
+ ISOLATED,
+
+ /** The read-external-storage permission cannot be granted */
+ DENIED
+ }
+
+ /**
+ * An app that is tested
+ */
+ private static class TestApp {
+ private static @NonNull Context sContext =
+ InstrumentationRegistry.getInstrumentation().getContext();
+ private static @NonNull AppOpsManager sAppOpsManager =
+ sContext.getSystemService(AppOpsManager.class);
+ private static @NonNull PackageManager sPackageManager = sContext.getPackageManager();
+
+ private final String mApk;
+ private final String mPkg;
+
+ public final boolean isRestricted;
+ public final boolean hasRequestedLegacyExternalStorage;
+
+ TestApp(@NonNull String apk, @NonNull String pkg, boolean isRestricted,
+ @NonNull boolean hasRequestedLegacyExternalStorage) {
+ mApk = apk;
+ mPkg = pkg;
+
+ this.isRestricted = isRestricted;
+ this.hasRequestedLegacyExternalStorage = hasRequestedLegacyExternalStorage;
+ }
+
+ /**
+ * Assert that the read-external-storage permission was granted or not granted.
+ *
+ * @param expectGranted {@code true} if the permission is expected to be granted
+ */
+ void assertStoragePermGranted(boolean expectGranted) {
+ eventually(() -> assertWithMessage(this + " read storage granted").that(
+ isGranted(mPkg, READ_EXTERNAL_STORAGE)).isEqualTo(expectGranted));
+ }
+
+ /**
+ * Assert that the app has non-isolated storage
+ *
+ * @param expectGranted {@code true} if the app is expected to have non-isolated storage
+ */
+ void assertHasNotIsolatedStorage(boolean expectHasNotIsolatedStorage) {
+ eventually(() -> runWithShellPermissionIdentity(() -> {
+ int uid = sContext.getPackageManager().getPackageUid(mPkg, 0);
+ if (expectHasNotIsolatedStorage) {
+ assertWithMessage(this + " legacy storage mode").that(
+ sAppOpsManager.unsafeCheckOpRawNoThrow(OPSTR_LEGACY_STORAGE, uid,
+ mPkg)).isEqualTo(MODE_ALLOWED);
+ } else {
+ assertWithMessage(this + " legacy storage mode").that(
+ sAppOpsManager.unsafeCheckOpRawNoThrow(OPSTR_LEGACY_STORAGE, uid,
+ mPkg)).isNotEqualTo(MODE_ALLOWED);
+ }
+ }));
+ }
+
+ int getTargetSDK() throws Exception {
+ return sPackageManager.getApplicationInfo(mPkg, 0).targetSdkVersion;
+ }
+
+ void install() {
+ if (isRestricted) {
+ runShellCommandOrThrow(
+ "pm install -g --force-queryable --restrict-permissions " + mApk);
+ } else {
+ runShellCommandOrThrow("pm install -g --force-queryable " + mApk);
+ }
+ }
+
+ void uninstall() {
+ runShellCommand("pm uninstall " + mPkg);
+ }
+
+ @Override
+ public String toString() {
+ return mPkg.substring(PKG_PREFIX.length());
+ }
+ }
+
+ /**
+ * Placeholder for "no app". The properties are chosen that when combined with another app, the
+ * other app always decides the resulting property,
+ */
+ private static class NoApp extends TestApp {
+ NoApp() {
+ super("", PKG_PREFIX + "(none)", true, false);
+ }
+
+ void assertStoragePermGranted(boolean ignored) {
+ // empty
+ }
+
+ void assertHasNotIsolatedStorage(boolean ignored) {
+ // empty
+ }
+
+ @Override
+ int getTargetSDK() {
+ return 10000;
+ }
+
+ @Override
+ public void install() {
+ // empty
+ }
+
+ @Override
+ public void uninstall() {
+ // empty
+ }
+ }
+
+ private static final String APK_PATH = "/data/local/tmp/cts-permissionpolicy/";
+ private static final String PKG_PREFIX = "android.permissionpolicy.cts.legacystoragewithshareduid.";
+
+ private static final TestApp[] TEST_APPS = new TestApp[]{
+ new TestApp(APK_PATH + "CtsLegacyStorageNotIsolatedWithSharedUid.apk",
+ PKG_PREFIX + "notisolated", false, true),
+ new TestApp(APK_PATH + "CtsLegacyStorageIsolatedWithSharedUid.apk",
+ PKG_PREFIX + "isolated", false, false),
+ new TestApp(APK_PATH + "CtsLegacyStorageRestrictedWithSharedUid.apk",
+ PKG_PREFIX + "restricted", true, false),
+ new TestApp(APK_PATH + "CtsLegacyStorageRestrictedSdk28WithSharedUid.apk",
+ PKG_PREFIX + "restrictedsdk28", true, true),
+ new NoApp()};
+
+ /**
+ * First app to be tested. This is the first in an entry created by {@link
+ * #getTestAppCombinations}
+ */
+ @Parameter(0)
+ public @NonNull TestApp app1;
+
+ /**
+ * Second app to be tested. This is the second in an entry created by {@link
+ * #getTestAppCombinations}
+ */
+ @Parameter(1)
+ public @NonNull TestApp app2;
+
+ /**
+ * Run this test for all combination of two tests-apps out of {@link #TEST_APPS}. This includes
+ * the {@link NoApp}, i.e. we also test a single test-app by itself.
+ *
+ * @return All combinations of two test-apps
+ */
+ @Parameters(name = "{0} and {1}")
+ public static Iterable<Object[]> getTestAppCombinations() {
+ ArrayList<Object[]> parameters = new ArrayList<>();
+
+ for (int firstApp = 0; firstApp < TEST_APPS.length; firstApp++) {
+ for (int secondApp = firstApp + 1; secondApp < TEST_APPS.length; secondApp++) {
+ parameters.add(new Object[]{TEST_APPS[firstApp], TEST_APPS[secondApp]});
+ }
+ }
+
+ return parameters;
+ }
+
+ @Test
+ public void checkExceptedStorageStateForAppsSharingUid() throws Exception {
+ app1.install();
+ app2.install();
+
+ int targetSDK = min(app1.getTargetSDK(), app2.getTargetSDK());
+ boolean isRestricted = app1.isRestricted && app2.isRestricted;
+ boolean hasRequestedLegacyExternalStorage =
+ app1.hasRequestedLegacyExternalStorage || app2.hasRequestedLegacyExternalStorage;
+
+ StorageState expectedState;
+ if (isRestricted) {
+ if (targetSDK < Build.VERSION_CODES.Q) {
+ expectedState = DENIED;
+ } else {
+ expectedState = ISOLATED;
+ }
+ } else if (hasRequestedLegacyExternalStorage && targetSDK <= Build.VERSION_CODES.Q) {
+ expectedState = NON_ISOLATED;
+ } else {
+ expectedState = ISOLATED;
+ }
+
+ Log.i(LOG_TAG, "Expected state=" + expectedState);
+
+ app1.assertStoragePermGranted(expectedState != DENIED);
+ app2.assertStoragePermGranted(expectedState != DENIED);
+
+ if (expectedState != DENIED) {
+ app1.assertHasNotIsolatedStorage(expectedState == NON_ISOLATED);
+ app2.assertHasNotIsolatedStorage(expectedState == NON_ISOLATED);
+ }
+ }
+
+ @After
+ public void uninstallAllTestPackages() {
+ app1.uninstall();
+ app2.uninstall();
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionTest.java b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionTest.java
new file mode 100644
index 000000000..6a3b0711d
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RestrictedStoragePermissionTest.java
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2020 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.permissionpolicy.cts;
+
+import static android.permission.cts.PermissionUtils.isGranted;
+import static android.permission.cts.PermissionUtils.isPermissionGranted;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.Manifest;
+import android.Manifest.permission;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.platform.test.annotations.AppModeFull;
+import android.util.ArraySet;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ThrowingRunnable;
+import com.android.modules.utils.build.SdkLevel;
+
+import org.junit.After;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/** Tests for restricted storage-related permissions. */
+public class RestrictedStoragePermissionTest {
+ private static final String APK_USES_STORAGE_DEFAULT_22 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk22.apk";
+
+ private static final String APK_USES_STORAGE_DEFAULT_28 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk28.apk";
+
+ private static final String APK_USES_STORAGE_DEFAULT_29 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserDefaultSdk29.apk";
+
+ private static final String APK_USES_STORAGE_OPT_IN_22 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptInSdk22.apk";
+
+ private static final String APK_USES_STORAGE_OPT_IN_28 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptInSdk28.apk";
+
+ private static final String APK_USES_STORAGE_OPT_OUT_29 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptOutSdk29.apk";
+
+ private static final String APK_USES_STORAGE_OPT_OUT_30 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsUserOptOutSdk30.apk";
+
+ private static final String APK_USES_STORAGE_PRESERVED_OPT_OUT_30 =
+ "/data/local/tmp/cts-permissionpolicy/CtsStoragePermissionsPreservedUserOptOutSdk30.apk";
+
+ private static final String PKG = "android.permissionpolicy.cts.restrictedpermissionuser";
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk22DefaultWhitelistedHasFullAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_22, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk22OptInWhitelistedHasIsolatedAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_22, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28DefaultWhitelistedHasFullAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28OptInWhitelistedHasIsolatedAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_28, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29DefaultWhitelistedHasIsolatedAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet());
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29DefaultNotWhitelistedHasIsolatedAccess() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_29, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29OptOutWhitelistedHasFullAccess() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null /*whitelistedPermissions*/);
+
+ // Check expected storage mode
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29OptOutNotWhitelistedHasIsolatedAccess() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet());
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29CanOptOutViaUpdate() throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29CanOptOutViaDowngradeTo28() throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk30_cannotOptOut() throws Exception {
+ // Apps that target R and above cannot opt out of isolated storage.
+ installApp(APK_USES_STORAGE_OPT_OUT_30, null);
+
+ // Check expected storage mode
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28CanRemoveOptInViaUpdate() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_IN_28, null);
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28CanRemoveOptInByOptingOut() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_IN_28, null);
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28DoesNotLoseAccessWhenOptingIn() throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+ assertHasFullStorageAccess();
+ installApp(APK_USES_STORAGE_OPT_IN_28, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28DoesNotLoseAccessViaUpdate() throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+ assertHasFullStorageAccess();
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29DoesNotLoseAccessViaUpdate() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29DoesNotLoseAccessWhenOptingIn() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
+ installApp(APK_USES_STORAGE_OPT_IN_28, null);
+
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk29LosesAccessViaUpdateToTargetSdk30() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
+
+ installApp(APK_USES_STORAGE_OPT_OUT_30, null); // opt-out is a no-op on 30
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testTargetingSdk28LosesAccessViaUpdateToTargetSdk30() throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+ assertHasFullStorageAccess();
+
+ installApp(APK_USES_STORAGE_OPT_OUT_30, null); // opt-out is a no-op on 30
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testCannotControlStorageWhitelistPostInstall1() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_28, null /*whitelistedPermissions*/);
+
+ // Check expected state of restricted permissions.
+ assertCannotUnWhitelistStorage();
+ }
+
+ @Test
+ @AppModeFull
+ public void testCannotControlStorageWhitelistPostInstall2() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
+
+ // Check expected state of restricted permissions.
+ assertCannotWhitelistStorage();
+ }
+
+ @Test
+ @AppModeFull
+ public void cannotGrantStorageTargetingSdk22NotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_22, Collections.emptySet());
+
+ eventually(() -> {
+ // Could not grant permission+app-op as targetSDK<29 and not whitelisted
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse();
+
+ // Permissions are always granted for pre-23 apps
+ assertThat(isPermissionGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE))
+ .isTrue();
+ });
+ }
+
+ @Test
+ @AppModeFull
+ public void cannotGrantStorageTargetingSdk22OptInNotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_22, Collections.emptySet());
+
+ eventually(() -> {
+ // Could not grant permission as targetSDK<29 and not whitelisted
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse();
+
+ // Permissions are always granted for pre-23 apps
+ assertThat(isPermissionGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE))
+ .isTrue();
+ });
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk22Whitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_22, null);
+
+ // Could grant permission
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk22OptInWhitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_22, null);
+
+ // Could grant permission
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void cannotGrantStorageTargetingSdk28NotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_28, Collections.emptySet());
+
+ // Could not grant permission as targetSDK<29 and not whitelisted
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse());
+ }
+
+ @Test
+ @AppModeFull
+ public void cannotGrantStorageTargetingSdk28OptInNotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_28, Collections.emptySet());
+
+ // Could not grant permission as targetSDK<29 and not whitelisted
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isFalse());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk28Whitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_28, null);
+
+ // Could grant permission
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk28OptInWhitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_IN_28, null);
+
+ // Could grant permission
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk29NotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_29, Collections.emptySet());
+
+ // Could grant permission as targetSDK=29 apps can always grant
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk29OptOutNotWhitelisted() throws Exception {
+ // Install with no whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_OUT_29, Collections.emptySet());
+
+ // Could grant permission as targetSDK=29 apps can always grant
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk29Whitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+
+ // Could grant permission as targetSDK=29 apps can always grant
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void canGrantStorageTargetingSdk29OptOutWhitelisted() throws Exception {
+ // Install with whitelisted permissions.
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+
+ // Could grant permission as targetSDK=29 apps can always grant
+ eventually(() ->
+ assertThat(isGranted(PKG, Manifest.permission.READ_EXTERNAL_STORAGE)).isTrue());
+ }
+
+ @Test
+ @AppModeFull
+ public void restrictedWritePermDoesNotImplyIsolatedStorageAccess() throws Exception {
+ // Install with whitelisted read permissions.
+ installApp(
+ APK_USES_STORAGE_OPT_OUT_29,
+ Collections.singleton(Manifest.permission.READ_EXTERNAL_STORAGE));
+
+ // It does not matter that write is restricted as the storage access level is only
+ // controlled by the read perm
+ assertHasFullStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void whitelistedWritePermDoesNotImplyFullStorageAccess() throws Exception {
+ // Install with whitelisted read permissions.
+ installApp(
+ APK_USES_STORAGE_OPT_OUT_29,
+ Collections.singleton(Manifest.permission.WRITE_EXTERNAL_STORAGE));
+
+ // It does not matter that write is white listed as the storage access level is only
+ // controlled by the read perm
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testStorageTargetingSdk30CanPreserveLegacyOnUpdateFromLegacy() throws Exception {
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
+
+ // Updating with the flag preserves legacy
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+ assertHasFullStorageAccess();
+
+ // And with the flag still preserves legacy
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+ assertHasFullStorageAccess();
+
+ // But without the flag loses legacy
+ installApp(APK_USES_STORAGE_OPT_OUT_30, null);
+ assertHasIsolatedStorageAccess();
+
+ // And again with the flag doesn't bring back legacy
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testStorageTargetingSdk30CannotPreserveLegacyAfterLegacyUninstall()
+ throws Exception {
+ installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
+
+ runShellCommand("pm uninstall " + PKG);
+
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testStorageTargetingSdk30CannotPreserveLegacyOnUpdateFromNonLegacy()
+ throws Exception {
+ installApp(APK_USES_STORAGE_DEFAULT_29, null);
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+
+ assertHasIsolatedStorageAccess();
+ }
+
+ @Test
+ @AppModeFull
+ public void testStorageTargetingSdk30CannotPreserveLegacyOnInstall() throws Exception {
+ installApp(APK_USES_STORAGE_PRESERVED_OPT_OUT_30, null);
+
+ assertHasIsolatedStorageAccess();
+ }
+
+ private void assertHasFullStorageAccess() throws Exception {
+ runWithShellPermissionIdentity(() -> {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final int uid = getContext().getPackageManager().getPackageUid(PKG, 0);
+ eventually(() -> assertThat(appOpsManager.unsafeCheckOpRawNoThrow(
+ AppOpsManager.OPSTR_LEGACY_STORAGE,
+ uid, PKG)).isEqualTo(AppOpsManager.MODE_ALLOWED));
+ });
+ }
+
+ private void assertHasIsolatedStorageAccess() throws Exception {
+ runWithShellPermissionIdentity(() -> {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ final int uid = getContext().getPackageManager().getPackageUid(PKG, 0);
+ eventually(() -> assertThat(appOpsManager.unsafeCheckOpRawNoThrow(
+ AppOpsManager.OPSTR_LEGACY_STORAGE,
+ uid, PKG)).isNotEqualTo(AppOpsManager.MODE_ALLOWED));
+ });
+ }
+
+ private void assertCannotWhitelistStorage() throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+
+ runWithShellPermissionIdentity(() -> {
+ // Assert added only to none whitelist.
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .doesNotContain(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
+ });
+
+ // Assert we cannot add.
+ try {
+ packageManager.addWhitelistedRestrictedPermission(
+ PKG,
+ permission.READ_EXTERNAL_STORAGE,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ packageManager.addWhitelistedRestrictedPermission(
+ PKG,
+ permission.WRITE_EXTERNAL_STORAGE,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ fail();
+ } catch (SecurityException expected) {
+ }
+
+ runWithShellPermissionIdentity(() -> {
+ // Assert added only to none whitelist.
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .doesNotContain(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
+ });
+ }
+
+ private void assertCannotUnWhitelistStorage() throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+
+ runWithShellPermissionIdentity(() -> {
+ // Assert added only to install whitelist.
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .contains(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .contains(permission.WRITE_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
+ .doesNotContain(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
+ .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
+ });
+
+ try {
+ // Assert we cannot remove.
+ packageManager.removeWhitelistedRestrictedPermission(
+ PKG,
+ permission.READ_EXTERNAL_STORAGE,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ fail();
+ } catch (SecurityException expected) {
+ }
+ try {
+ packageManager.removeWhitelistedRestrictedPermission(
+ PKG,
+ permission.WRITE_EXTERNAL_STORAGE,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ fail();
+ } catch (SecurityException expected) {
+ }
+
+ runWithShellPermissionIdentity(() -> {
+ // Assert added only to install whitelist.
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .contains(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER))
+ .contains(permission.WRITE_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
+ .doesNotContain(permission.READ_EXTERNAL_STORAGE);
+ assertThat(packageManager.getWhitelistedRestrictedPermissions(PKG,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM))
+ .doesNotContain(permission.WRITE_EXTERNAL_STORAGE);
+ });
+ }
+
+ private @NonNull Set<String> getPermissionsOfAppWithAnyOfFlags(int flags) throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final Set<String> restrictedPermissions = new ArraySet<>();
+ for (String permission : getRequestedPermissionsOfApp()) {
+ PermissionInfo permInfo = packageManager.getPermissionInfo(permission, 0);
+
+ if ((permInfo.flags & flags) != 0) {
+ restrictedPermissions.add(permission);
+ }
+ }
+ return restrictedPermissions;
+ }
+
+ private @NonNull Set<String> getRestrictedPermissionsOfApp() throws Exception {
+ return getPermissionsOfAppWithAnyOfFlags(
+ PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED);
+ }
+
+ private @NonNull String[] getRequestedPermissionsOfApp() throws Exception {
+ final PackageManager packageManager = getContext().getPackageManager();
+ final PackageInfo packageInfo =
+ packageManager.getPackageInfo(PKG, PackageManager.GET_PERMISSIONS);
+ return packageInfo.requestedPermissions;
+ }
+
+ private static @NonNull Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getContext();
+ }
+
+ private static void runWithShellPermissionIdentity(@NonNull ThrowingRunnable command)
+ throws Exception {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity();
+ try {
+ command.run();
+ } finally {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Install an app.
+ *
+ * @param app The app to be installed
+ * @param whitelistedPermissions The permission to be whitelisted. {@code null} == all
+ * @param grantedPermissions The permission to be granted. {@code null} == all
+ */
+ private void installApp(
+ @NonNull String app,
+ @Nullable Set<String> whitelistedPermissions)
+ throws Exception {
+ String bypassLowTargetSdkFlag = "";
+ if (SdkLevel.isAtLeastU()) {
+ bypassLowTargetSdkFlag = " --bypass-low-target-sdk-block";
+ }
+
+ // Install the app and whitelist/grant all permission if requested.
+ String installResult = runShellCommandOrThrow("pm install"
+ + bypassLowTargetSdkFlag + " -t -r --restrict-permissions " + app);
+ assertThat(installResult.trim()).isEqualTo("Success");
+
+ final Set<String> adjustedWhitelistedPermissions;
+ if (whitelistedPermissions == null) {
+ adjustedWhitelistedPermissions = getRestrictedPermissionsOfApp();
+ } else {
+ adjustedWhitelistedPermissions = whitelistedPermissions;
+ }
+
+ final Set<String> adjustedGrantedPermissions = getRestrictedPermissionsOfApp();
+
+ // Whitelist subset of permissions if requested
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : adjustedWhitelistedPermissions) {
+ packageManager.addWhitelistedRestrictedPermission(
+ PKG,
+ permission,
+ PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ }
+ });
+
+ // Grant subset of permissions if requested
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : adjustedGrantedPermissions) {
+ packageManager.grantRuntimePermission(PKG, permission, getContext().getUser());
+ packageManager.updatePermissionFlags(
+ permission,
+ PKG,
+ PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
+ 0,
+ getContext().getUser());
+ }
+ });
+
+ // Mark all permissions as reviewed as for pre-22 apps the restriction state might not be
+ // applied until reviewed
+ runWithShellPermissionIdentity(() -> {
+ final PackageManager packageManager = getContext().getPackageManager();
+ for (String permission : getRequestedPermissionsOfApp()) {
+ packageManager.updatePermissionFlags(
+ permission,
+ PKG,
+ PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
+ 0,
+ getContext().getUser());
+ }
+ });
+ }
+
+ @After
+ public void uninstallApp() {
+ runShellCommand("pm uninstall " + PKG);
+ }
+}
diff --git a/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RuntimePermissionProperties.kt b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RuntimePermissionProperties.kt
new file mode 100644
index 000000000..0e35b9228
--- /dev/null
+++ b/tests/cts/permissionpolicy/src/android/permissionpolicy/cts/RuntimePermissionProperties.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2019 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.permissionpolicy.cts
+
+import android.Manifest.permission.ACCEPT_HANDOVER
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.ACTIVITY_RECOGNITION
+import android.Manifest.permission.ADD_VOICEMAIL
+import android.Manifest.permission.ANSWER_PHONE_CALLS
+import android.Manifest.permission.BLUETOOTH_ADVERTISE
+import android.Manifest.permission.BLUETOOTH_CONNECT
+import android.Manifest.permission.BLUETOOTH_SCAN
+import android.Manifest.permission.BODY_SENSORS
+import android.Manifest.permission.CALL_PHONE
+import android.Manifest.permission.CAMERA
+import android.Manifest.permission.GET_ACCOUNTS
+import android.Manifest.permission.NEARBY_WIFI_DEVICES
+import android.Manifest.permission.PACKAGE_USAGE_STATS
+import android.Manifest.permission.POST_NOTIFICATIONS
+import android.Manifest.permission.PROCESS_OUTGOING_CALLS
+import android.Manifest.permission.READ_CALENDAR
+import android.Manifest.permission.READ_CALL_LOG
+import android.Manifest.permission.READ_CELL_BROADCASTS
+import android.Manifest.permission.READ_CONTACTS
+import android.Manifest.permission.READ_EXTERNAL_STORAGE
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+import android.Manifest.permission.READ_PHONE_NUMBERS
+import android.Manifest.permission.READ_PHONE_STATE
+import android.Manifest.permission.READ_SMS
+import android.Manifest.permission.RECEIVE_MMS
+import android.Manifest.permission.RECEIVE_SMS
+import android.Manifest.permission.RECEIVE_WAP_PUSH
+import android.Manifest.permission.RECORD_AUDIO
+import android.Manifest.permission.SEND_SMS
+import android.Manifest.permission.USE_SIP
+import android.Manifest.permission.UWB_RANGING
+import android.Manifest.permission.WRITE_CALENDAR
+import android.Manifest.permission.WRITE_CALL_LOG
+import android.Manifest.permission.WRITE_CONTACTS
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.Manifest.permission_group.UNDEFINED
+import android.app.AppOpsManager.permissionToOp
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.GET_PERMISSIONS
+import android.content.pm.PermissionInfo.PROTECTION_DANGEROUS
+import android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP
+import android.os.Build
+import android.permission.PermissionManager
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class RuntimePermissionProperties {
+ private val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
+ private val pm = context.packageManager
+
+ private val platformPkg = pm.getPackageInfo("android", GET_PERMISSIONS)
+ private val platformRuntimePerms = platformPkg.permissions
+ .filter { it.protection == PROTECTION_DANGEROUS }
+ private val platformBgPermNames = platformRuntimePerms.mapNotNull { it.backgroundPermission }
+
+ @Test
+ fun allRuntimeForegroundPermissionNeedAnAppOp() {
+ val platformFgPerms =
+ platformRuntimePerms.filter { !platformBgPermNames.contains(it.name) }
+
+ for (perm in platformFgPerms) {
+ assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNotNull()
+ }
+ }
+
+ @Test
+ fun groupOfRuntimePermissionsShouldBeUnknown() {
+ for (perm in platformRuntimePerms) {
+ assertWithMessage("Group of ${perm.name}").that(perm.group).isEqualTo(UNDEFINED)
+ }
+ }
+
+ @Test
+ fun allAppOpPermissionNeedAnAppOp() {
+ val platformAppOpPerms = platformPkg.permissions
+ .filter { (it.protectionFlags and PROTECTION_FLAG_APPOP) != 0 }
+ .filter {
+ // Grandfather incomplete definition of PACKAGE_USAGE_STATS
+ it.name != PACKAGE_USAGE_STATS
+ }
+
+ for (perm in platformAppOpPerms) {
+ assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNotNull()
+ }
+ }
+
+ /**
+ * The permission of a background permission is the one of its foreground permission
+ */
+ @Test
+ fun allRuntimeBackgroundPermissionCantHaveAnAppOp() {
+ val platformBgPerms =
+ platformRuntimePerms.filter { platformBgPermNames.contains(it.name) }
+
+ for (perm in platformBgPerms) {
+ assertWithMessage("AppOp for ${perm.name}").that(permissionToOp(perm.name)).isNull()
+ }
+ }
+
+ /**
+ * Commonly a new runtime permission is created by splitting an old one into twice
+ */
+ @Test
+ fun runtimePermissionsShouldHaveBeenSplitFromPreviousPermission() {
+ // Runtime permissions in Android P
+ val expectedPerms = mutableSetOf(READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS, READ_CALENDAR,
+ WRITE_CALENDAR, SEND_SMS, RECEIVE_SMS, READ_SMS, RECEIVE_MMS, RECEIVE_WAP_PUSH,
+ READ_CELL_BROADCASTS, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE,
+ ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, READ_CALL_LOG, WRITE_CALL_LOG,
+ PROCESS_OUTGOING_CALLS, READ_PHONE_STATE, READ_PHONE_NUMBERS, CALL_PHONE,
+ ADD_VOICEMAIL, USE_SIP, ANSWER_PHONE_CALLS, ACCEPT_HANDOVER, RECORD_AUDIO, CAMERA,
+ BODY_SENSORS)
+
+ // Add permission split since P
+ for (sdkVersion in Build.VERSION_CODES.P + 1..Build.VERSION_CODES.CUR_DEVELOPMENT + 1) {
+ for (splitPerm in
+ context.getSystemService(PermissionManager::class.java)!!.splitPermissions) {
+ if (splitPerm.targetSdk == sdkVersion &&
+ expectedPerms.contains(splitPerm.splitPermission)) {
+ expectedPerms.addAll(splitPerm.newPermissions)
+ }
+ }
+ }
+
+ // Add runtime permission added in Q which were _not_ split from a previously existing
+ // runtime permission
+ expectedPerms.add(ACTIVITY_RECOGNITION)
+
+ // Add runtime permissions added in S which were _not_ split from a previously existing
+ // runtime permission
+ expectedPerms.add(BLUETOOTH_ADVERTISE)
+ expectedPerms.add(BLUETOOTH_CONNECT)
+ expectedPerms.add(BLUETOOTH_SCAN)
+ expectedPerms.add(UWB_RANGING)
+
+ // Add runtime permissions added in T which were _not_ split from a previously existing
+ // runtime permission
+ expectedPerms.add(POST_NOTIFICATIONS)
+ expectedPerms.add(NEARBY_WIFI_DEVICES)
+
+ // Add runtime permissions added in U which were _not_ split from a previously existing
+ // runtime permission
+ expectedPerms.add(READ_MEDIA_VISUAL_USER_SELECTED)
+
+ assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
+ }
+}
diff --git a/tests/cts/permissionui/Android.bp b/tests/cts/permissionui/Android.bp
new file mode 100644
index 000000000..0e18b67c6
--- /dev/null
+++ b/tests/cts/permissionui/Android.bp
@@ -0,0 +1,84 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsPermissionUiTestCases",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.kt",
+ ":CtsProviderTestUtils",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "bluetooth-test-util-lib",
+ "modules-utils-build_system",
+ "androidx.test.core",
+ "permission-test-util-lib",
+ "sts-device-util",
+ "cts-wm-util",
+ "flag-junit",
+ "CtsAccessibilityCommon",
+ "CtsVirtualDeviceCommonLib",
+ "android.companion.virtual.flags-aconfig-java",
+ "platform-test-rules",
+ "platform-test-annotations",
+ ],
+ data: [
+ ":CtsPermissionPolicyApp25",
+ ":CtsUsePermissionApp22",
+ ":CtsUsePermissionApp22CalendarOnly",
+ ":CtsUsePermissionApp22None",
+ ":CtsUsePermissionApp23",
+ ":CtsUsePermissionApp25",
+ ":CtsUsePermissionApp26",
+ ":CtsUsePermissionApp28",
+ ":CtsUsePermissionApp29",
+ ":CtsUsePermissionApp30",
+ ":CtsUsePermissionApp30WithBackground",
+ ":CtsUsePermissionApp30WithBluetooth",
+ ":CtsUsePermissionApp31",
+ ":CtsUsePermissionApp32",
+ ":CtsUsePermissionAppStreaming",
+ ":CtsUsePermissionAppLatest",
+ ":CtsUsePermissionAppLatestNone",
+ ":CtsUsePermissionAppWithOverlay",
+ ":CtsAccessMicrophoneAppLocationProvider",
+ ":CtsHelperAppOverlay",
+ ":CtsCreateNotificationChannelsApp31",
+ ":CtsMediaPermissionApp33WithStorage",
+ ":CtsDifferentPkgNameApp",
+ ":CtsUsePermissionAppImplicitUserSelectStorage",
+ ":CtsAppThatAccessesMicAndCameraPermission",
+ ":CtsUsePermissionAppStorage33",
+ ],
+ test_suites: [
+ "cts",
+ "sts",
+ "general-tests",
+ "mts-permission",
+ "automotive-tests",
+ "automotive-general-tests",
+ ],
+}
diff --git a/tests/cts/permissionui/AndroidManifest.xml b/tests/cts/permissionui/AndroidManifest.xml
new file mode 100644
index 000000000..3b80b8d8b
--- /dev/null
+++ b/tests/cts/permissionui/AndroidManifest.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.GET_TASKS" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+
+ <application>
+
+ <uses-library android:name="android.test.runner" />
+
+ <service android:name="android.permission.cts.CtsNotificationListenerService"
+ android:exported="true"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService"/>
+ </intent-filter>
+ </service>
+
+ <activity android:name="com.android.compatibility.common.util.FutureResultActivity" />
+ <activity
+ android:name=".StartForFutureActivity"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"/>
+
+ <activity android:name=".TestInstallerActivity"
+ android:exported="true"
+ android:enabled="false"
+ android:launchMode="singleInstance">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_APP_INFO" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".AccessibilityTestService1"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:label="@string/test_accessibility_service"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/test_accessibilityservice"/>
+ </service>
+
+ <service android:name=".AccessibilityTestService2"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+ android:label="@string/test_accessibility_service_2"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/test_accessibilityservice"/>
+ </service>
+
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.permissionui.cts"
+ android:label="CTS UI tests for permissions">
+ </instrumentation>
+</manifest>
diff --git a/tests/cts/permissionui/AndroidTest.xml b/tests/cts/permissionui/AndroidTest.xml
new file mode 100644
index 000000000..57591d93e
--- /dev/null
+++ b/tests/cts/permissionui/AndroidTest.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<configuration description="Config for CTS Permission UI test cases">
+
+ <option name="test-suite-tag" value="cts" />
+
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" />
+
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <!-- Keep screen on for Bluetooth scanning -->
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
+ <option name="restore-settings" value="true" />
+ <option name="disable-device-config-sync" value="true" />
+ <option name="screen-always-on" value="on" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPermissionUiTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="CtsAccessMicrophoneAppLocationProvider.apk->/data/local/tmp/cts-permissionui/CtsAccessMicrophoneAppLocationProvider.apk" />
+ <option name="push" value="CtsPermissionPolicyApp25.apk->/data/local/tmp/cts-permissionui/CtsPermissionPolicyApp25.apk" />
+ <option name="push" value="CtsUsePermissionApp22.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp22.apk" />
+ <option name="push" value="CtsUsePermissionApp22CalendarOnly.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp22CalendarOnly.apk" />
+ <option name="push" value="CtsUsePermissionApp22None.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp22None.apk" />
+ <option name="push" value="CtsUsePermissionApp23.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp23.apk" />
+ <option name="push" value="CtsUsePermissionApp25.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp25.apk" />
+ <option name="push" value="CtsUsePermissionApp26.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp26.apk" />
+ <option name="push" value="CtsUsePermissionApp28.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp28.apk" />
+ <option name="push" value="CtsUsePermissionApp29.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp29.apk" />
+ <option name="push" value="CtsUsePermissionApp30.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp30.apk" />
+ <option name="push" value="CtsUsePermissionApp30WithBackground.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp30WithBackground.apk" />
+ <option name="push" value="CtsUsePermissionApp30WithBluetooth.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp30WithBluetooth.apk" />
+ <option name="push" value="CtsUsePermissionApp31.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp31.apk" />
+ <option name="push" value="CtsUsePermissionApp32.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionApp32.apk" />
+ <option name="push" value="CtsUsePermissionAppStreaming.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppStreaming.apk" />
+ <option name="push" value="CtsUsePermissionAppLatest.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppLatest.apk" />
+ <option name="push" value="CtsUsePermissionAppLatestNone.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppLatestNone.apk" />
+ <option name="push" value="CtsUsePermissionAppWithOverlay.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppWithOverlay.apk" />
+ <option name="push" value="CtsHelperAppOverlay.apk->/data/local/tmp/cts-permissionui/CtsHelperAppOverlay.apk" />
+ <option name="push" value="CtsCreateNotificationChannelsApp31.apk->/data/local/tmp/cts-permissionui/CtsCreateNotificationChannelsApp31.apk" />
+ <option name="push" value="CtsDifferentPkgNameApp.apk->/data/local/tmp/cts-permissionui/CtsDifferentPkgNameApp.apk" />
+ <option name="push" value="CtsMediaPermissionApp33WithStorage.apk->/data/local/tmp/cts-permissionui/CtsMediaPermissionApp33WithStorage.apk" />
+ <option name="push" value="CtsUsePermissionAppImplicitUserSelectStorage.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppImplicitUserSelectStorage.apk" />
+ <option name="push" value="CtsAppThatAccessesMicAndCameraPermission.apk->/data/local/tmp/cts-permissionui/CtsAppThatAccessesMicAndCameraPermission.apk" />
+ <option name="push" value="CtsUsePermissionAppStorage33.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppStorage33.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="appops set android.permissionui.cts REQUEST_INSTALL_PACKAGES allow" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
+ <!-- ensure user setup is completed -->
+ <option name="run-command" value="settings put secure user_setup_complete 1" />
+ <!-- disable DeprecatedAbi warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_abi_dialog 1" />
+ <!-- disable DeprecatedTargetSdk warning -->
+ <option name="run-command" value="setprop debug.wm.disable_deprecated_target_sdk_dialog 1" />
+ </target_preparer>
+
+ <!-- Create place to store apks -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts-permissionui" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts-permissionui"/>
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/user/0/android.permissionui.cts/files" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.permissionui.cts" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+</configuration>
diff --git a/tests/cts/permissionui/AppThatAccessesCameraAndMic/Android.bp b/tests/cts/permissionui/AppThatAccessesCameraAndMic/Android.bp
new file mode 100644
index 000000000..e0d9fd791
--- /dev/null
+++ b/tests/cts/permissionui/AppThatAccessesCameraAndMic/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatAccessesMicAndCameraPermission",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "31",
+
+ static_libs: [
+ "androidx.test.rules",
+ "kotlin-stdlib",
+ "kotlinx-coroutines-android",
+ ],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
diff --git a/tests/cts/permissionui/AppThatAccessesCameraAndMic/AndroidManifest.xml b/tests/cts/permissionui/AppThatAccessesCameraAndMic/AndroidManifest.xml
new file mode 100644
index 000000000..e1130fbaa
--- /dev/null
+++ b/tests/cts/permissionui/AppThatAccessesCameraAndMic/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.appthataccessescameraandmic"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.CAMERA"/>
+
+ <application android:label="CtsCameraMicAccess">
+ <activity android:name=".AccessCameraOrMicActivity"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="test.action.USE_CAMERA_OR_MIC" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/AppThatAccessesCameraAndMic/src/android/permissionui/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt b/tests/cts/permissionui/AppThatAccessesCameraAndMic/src/android/permissionui/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
new file mode 100644
index 000000000..4dd668ac7
--- /dev/null
+++ b/tests/cts/permissionui/AppThatAccessesCameraAndMic/src/android/permissionui/cts/appthataccessescameraandmic/AccessCameraOrMicActivity.kt
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts.appthataccessescameraandmic
+
+import android.app.Activity
+import android.app.AppOpsManager
+import android.hardware.camera2.CameraAccessException
+import android.hardware.camera2.CameraCaptureSession
+import android.hardware.camera2.CameraCharacteristics
+import android.hardware.camera2.CameraDevice
+import android.hardware.camera2.CameraManager
+import android.hardware.camera2.params.OutputConfiguration
+import android.hardware.camera2.params.SessionConfiguration
+import android.media.AudioFormat.CHANNEL_IN_MONO
+import android.media.AudioFormat.ENCODING_PCM_16BIT
+import android.media.AudioRecord
+import android.media.ImageReader
+import android.media.MediaRecorder.AudioSource.MIC
+import android.os.Bundle
+import android.os.Handler
+import android.os.Process
+import android.util.Log
+import android.util.Size
+import androidx.annotation.NonNull
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+private const val USE_CAMERA = "use_camera"
+private const val USE_MICROPHONE = "use_microphone"
+private const val USE_HOTWORD = "use_hotword"
+private const val FINISH_EARLY = "finish_early"
+private const val USE_DURATION_MS = 10000L
+private const val SAMPLE_RATE_HZ = 44100
+
+/**
+ * Activity which will, depending on the extra passed in the intent, use the camera, the microphone,
+ * or both.
+ */
+class AccessCameraOrMicActivity : Activity() {
+ private lateinit var cameraManager: CameraManager
+ private lateinit var cameraId: String
+ private var cameraDevice: CameraDevice? = null
+ private var recorder: AudioRecord? = null
+ private var appOpsManager: AppOpsManager? = null
+ private var cameraFinished = false
+ private var runCamera = false
+ private var backupCameraOpRunning = true
+ private var micFinished = false
+ private var runMic = false
+ private var hotwordFinished = false
+ private var runHotword = false
+ private var finishEarly = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ throw RuntimeException(
+ "Activity was recreated (perhaps due to a configuration change?) " +
+ "and this activity doesn't currently know how to gracefully handle " +
+ "configuration changes.")
+ }
+ }
+
+ override fun onStart() {
+ super.onStart()
+ runCamera = intent.getBooleanExtra(USE_CAMERA, false)
+ runMic = intent.getBooleanExtra(USE_MICROPHONE, false)
+ runHotword = intent.getBooleanExtra(USE_HOTWORD, false)
+ finishEarly = intent.getBooleanExtra(FINISH_EARLY, false)
+
+ if (runMic) {
+ useMic()
+ }
+
+ if (runCamera) {
+ useCamera()
+ }
+
+ if (runHotword) {
+ useHotword()
+ }
+ }
+
+ override fun finish() {
+ super.finish()
+ cameraDevice?.close()
+ cameraDevice = null
+ recorder?.stop()
+ recorder = null
+ if (runCamera) {
+ appOpsManager?.finishOp(AppOpsManager.OPSTR_CAMERA, Process.myUid(), packageName)
+ }
+ if (runHotword) {
+ appOpsManager?.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, Process.myUid(),
+ packageName)
+ }
+ appOpsManager = null
+ }
+
+ override fun onStop() {
+ super.onStop()
+ finish()
+ }
+
+ private val stateCallback = object : CameraDevice.StateCallback() {
+ override fun onOpened(@NonNull camDevice: CameraDevice) {
+ cameraDevice = camDevice
+ val config = cameraManager!!.getCameraCharacteristics(cameraId)
+ .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
+ val outputFormat = config!!.outputFormats[0]
+ val outputSize: Size = config!!.getOutputSizes(outputFormat)[0]
+ val handler = Handler(mainLooper)
+
+ val imageReader = ImageReader.newInstance(
+ outputSize.width, outputSize.height, outputFormat, 2)
+
+ val builder = cameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
+ builder.addTarget(imageReader.surface)
+ val captureRequest = builder.build()
+ val sessionConfiguration = SessionConfiguration(
+ SessionConfiguration.SESSION_REGULAR,
+ listOf(OutputConfiguration(imageReader.surface)),
+ mainExecutor,
+ object : CameraCaptureSession.StateCallback() {
+ override fun onConfigured(session: CameraCaptureSession) {
+ session.capture(captureRequest, null, handler)
+ }
+
+ override fun onConfigureFailed(session: CameraCaptureSession) {}
+
+ override fun onReady(session: CameraCaptureSession) {}
+ })
+
+ imageReader.setOnImageAvailableListener({
+ GlobalScope.launch {
+ delay(USE_DURATION_MS)
+ if (!backupCameraOpRunning) {
+ cameraFinished = true
+ if (!runMic || micFinished) {
+ finish()
+ }
+ }
+ }
+ }, handler)
+ cameraDevice!!.createCaptureSession(sessionConfiguration)
+ }
+
+ override fun onDisconnected(@NonNull camDevice: CameraDevice) {
+ Log.e("CameraMicIndicatorsPermissionTest", "camera disconnected")
+ startBackupCamera(camDevice)
+ }
+
+ override fun onError(@NonNull camDevice: CameraDevice, error: Int) {
+ Log.e("CameraMicIndicatorsPermissionTest", "camera error $error")
+ startBackupCamera(camDevice)
+ }
+ }
+
+ private fun startBackupCamera(camDevice: CameraDevice?) {
+ // Something went wrong with the camera. Fallback to direct app op usage
+ if (runCamera && !cameraFinished) {
+ backupCameraOpRunning = true
+ appOpsManager = getSystemService(AppOpsManager::class.java)
+ appOpsManager?.startOpNoThrow(AppOpsManager.OPSTR_CAMERA, Process.myUid(), packageName)
+
+ GlobalScope.launch {
+ delay(USE_DURATION_MS)
+ cameraFinished = true
+ backupCameraOpRunning = false
+ finishIfAllDone()
+ }
+ }
+ camDevice?.close()
+ if (camDevice == cameraDevice) {
+ cameraDevice = null
+ }
+ }
+
+ @Throws(CameraAccessException::class)
+ private fun useCamera() {
+ // TODO 192690992: determine why the camera manager code is flaky
+ startBackupCamera(null)
+ /*
+ cameraManager = getSystemService(CameraManager::class.java)!!
+ cameraId = cameraManager.cameraIdList[0]
+ cameraManager.openCamera(cameraId, mainExecutor, stateCallback)
+ */
+ }
+
+ private fun useMic() {
+ val minSize =
+ AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT)
+ recorder = AudioRecord(MIC, SAMPLE_RATE_HZ, CHANNEL_IN_MONO, ENCODING_PCM_16BIT, minSize)
+ recorder?.startRecording()
+ if (finishEarly) {
+ appOpsManager = getSystemService(AppOpsManager::class.java)
+ appOpsManager?.finishOp(AppOpsManager.OPSTR_RECORD_AUDIO, Process.myUid(), packageName)
+ return
+ }
+ GlobalScope.launch {
+ delay(USE_DURATION_MS)
+ micFinished = true
+ finishIfAllDone()
+ }
+ }
+
+ private fun useHotword() {
+ appOpsManager = getSystemService(AppOpsManager::class.java)
+ appOpsManager?.startOpNoThrow(AppOpsManager.OPSTR_RECORD_AUDIO_HOTWORD, Process.myUid(),
+ packageName)
+
+ GlobalScope.launch {
+ delay(USE_DURATION_MS)
+ hotwordFinished = true
+ finishIfAllDone()
+ }
+ }
+
+ private fun finishIfAllDone() {
+ if ((!runMic || micFinished) && (!runCamera || cameraFinished) &&
+ (!runHotword || hotwordFinished)) {
+ finish()
+ }
+ }
+}
diff --git a/tests/cts/permissionui/CreateNotificationChannelsApp31/Android.bp b/tests/cts/permissionui/CreateNotificationChannelsApp31/Android.bp
new file mode 100644
index 000000000..265a01c69
--- /dev/null
+++ b/tests/cts/permissionui/CreateNotificationChannelsApp31/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsCreateNotificationChannelsApp31",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "31",
+
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
diff --git a/tests/cts/permissionui/CreateNotificationChannelsApp31/AndroidManifest.xml b/tests/cts/permissionui/CreateNotificationChannelsApp31/AndroidManifest.xml
new file mode 100644
index 000000000..b342319f3
--- /dev/null
+++ b/tests/cts/permissionui/CreateNotificationChannelsApp31/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission"
+ android:versionCode="1">
+
+ <uses-sdk android:minSdkVersion="31" android:targetSdkVersion="31" />
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+ <application android:label="CreateNotif">
+ <activity android:name=".CreateNotificationChannelsActivity"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="usepermission.createchannels.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/CreateNotificationChannelsApp31/src/android/permissionui/cts/usepermission/CreateNotificationChannelsActivity.kt b/tests/cts/permissionui/CreateNotificationChannelsApp31/src/android/permissionui/cts/usepermission/CreateNotificationChannelsActivity.kt
new file mode 100644
index 000000000..4bc394cbc
--- /dev/null
+++ b/tests/cts/permissionui/CreateNotificationChannelsApp31/src/android/permissionui/cts/usepermission/CreateNotificationChannelsActivity.kt
@@ -0,0 +1,172 @@
+/*
+ * 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.permissionui.cts.usepermission
+
+import android.Manifest
+import android.app.Activity
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+
+const val EXTRA_CREATE_CHANNELS = "extra_create"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_START_SECOND_ACTIVITY = "extra_start_second_activity"
+const val EXTRA_START_SECOND_APP = "extra_start_second_app"
+const val SECONDARY_APP_INTENT = "emptyactivity.main"
+const val SECONDARY_APP_PKG = "android.permissionui.cts.usepermissionother"
+const val TEST_PKG = "android.permissionui.cts"
+const val CHANNEL_ID_31 = "test_channel_id"
+const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
+const val DELAY_MS = 1000L
+const val LONG_DELAY_MS = 2000L
+
+class CreateNotificationChannelsActivity : Activity() {
+ private lateinit var notificationManager: NotificationManager
+ private var launchActivityOnSecondResume = false
+ private var isFirstResume = true
+ private var windowHasFocus = false
+ private var pendingCreateChannel = false
+ private val handler = Handler(Looper.getMainLooper())
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ throw RuntimeException(
+ "Activity was recreated (perhaps due to a configuration change?) " +
+ "and this activity doesn't currently know how to gracefully handle " +
+ "configuration changes.")
+ }
+
+ registerReceiver(receiver, IntentFilter(BROADCAST_ACTION), RECEIVER_EXPORTED)
+ handleIntent(intent)
+ }
+
+ private fun handleIntent(providedIntent: Intent?, broacastAfterComplete: Boolean = false) {
+ if (providedIntent == null) {
+ return
+ }
+ val launchSecondActivity =
+ providedIntent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)
+ notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
+ if (providedIntent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
+ handler.postDelayed({
+ val intent2 = Intent(SECONDARY_APP_INTENT)
+ intent2.`package` = SECONDARY_APP_PKG
+ intent2.addCategory(Intent.CATEGORY_DEFAULT)
+ handler.postDelayed({
+ createChannel()
+ }, DELAY_MS)
+ startActivity(intent2)
+ }, LONG_DELAY_MS)
+ } else if (providedIntent.getBooleanExtra(EXTRA_CREATE_CHANNELS, false)) {
+ createChannel()
+ if (launchSecondActivity) {
+ launchActivityOnSecondResume = true
+ }
+ } else if (launchSecondActivity) {
+ launchSecondActivity()
+ }
+
+ if (providedIntent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
+ requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
+ }
+
+ if (providedIntent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
+ requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
+ }
+
+ if (broacastAfterComplete) {
+ sendBroadcast(Intent(BROADCAST_ACTION).setPackage(TEST_PKG))
+ }
+ }
+
+ private val receiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ handleIntent(intent, true)
+ }
+ }
+
+ private fun launchSecondActivity() {
+ handler.postDelayed({
+ val intent2 = Intent(Intent.ACTION_MAIN)
+ intent2.`package` = packageName
+ intent2.addCategory(Intent.CATEGORY_DEFAULT)
+ intent2.putExtra(EXTRA_CREATE_CHANNELS, true)
+ startActivity(intent2)
+ }, LONG_DELAY_MS)
+ }
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ windowHasFocus = hasFocus
+ if (windowHasFocus && pendingCreateChannel) {
+ pendingCreateChannel = false
+ createChannel()
+ }
+ }
+
+ private fun createChannel() {
+ // Wait until window has focus so the permission prompt can be displayed
+ if (!windowHasFocus) {
+ pendingCreateChannel = true
+ return
+ }
+
+ if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
+ notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
+ "Foreground Services", NotificationManager.IMPORTANCE_HIGH))
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (!isFirstResume && launchActivityOnSecondResume) {
+ launchSecondActivity()
+ }
+ isFirstResume = false
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ val grantedPerms = arrayListOf<String>()
+ for ((i, permName) in permissions.withIndex()) {
+ if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
+ grantedPerms.add(permName)
+ }
+ }
+ sendBroadcast(
+ Intent(BROADCAST_ACTION).putStringArrayListExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, grantedPerms)
+ .setPackage(TEST_PKG))
+ }
+
+ companion object {
+ private val TAG = CreateNotificationChannelsActivity::class.simpleName
+ }
+}
diff --git a/tests/cts/permissionui/DifferentPkgNameApp/Android.bp b/tests/cts/permissionui/DifferentPkgNameApp/Android.bp
new file mode 100644
index 000000000..3db3c30b2
--- /dev/null
+++ b/tests/cts/permissionui/DifferentPkgNameApp/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsDifferentPkgNameApp",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "31",
+
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
diff --git a/tests/cts/permissionui/DifferentPkgNameApp/AndroidManifest.xml b/tests/cts/permissionui/DifferentPkgNameApp/AndroidManifest.xml
new file mode 100644
index 000000000..d0b63b597
--- /dev/null
+++ b/tests/cts/permissionui/DifferentPkgNameApp/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermissionother"
+ android:versionCode="1">
+
+ <uses-sdk android:minSdkVersion="31" android:targetSdkVersion="31" />
+
+ <application android:label="EmptyActivity">
+ <activity android:name=".EmptyActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="emptyactivity.main" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/DifferentPkgNameApp/src/android/permissionui/cts/usepermissionother/EmptyActivity.kt b/tests/cts/permissionui/DifferentPkgNameApp/src/android/permissionui/cts/usepermissionother/EmptyActivity.kt
new file mode 100644
index 000000000..fc4518a90
--- /dev/null
+++ b/tests/cts/permissionui/DifferentPkgNameApp/src/android/permissionui/cts/usepermissionother/EmptyActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.permissionui.cts.usepermissionother
+
+import android.app.Activity
+
+class EmptyActivity : Activity()
diff --git a/tests/cts/permissionui/HelperAppOverlay/Android.bp b/tests/cts/permissionui/HelperAppOverlay/Android.bp
new file mode 100644
index 000000000..94d9653e9
--- /dev/null
+++ b/tests/cts/permissionui/HelperAppOverlay/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsHelperAppOverlay",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permissionui/HelperAppOverlay/AndroidManifest.xml b/tests/cts/permissionui/HelperAppOverlay/AndroidManifest.xml
new file mode 100644
index 000000000..b26459660
--- /dev/null
+++ b/tests/cts/permissionui/HelperAppOverlay/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.helper.overlay">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application>
+ <activity android:name=".OverlayActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/HelperAppOverlay/src/android/permissionui/cts/helper/overlay/OverlayActivity.kt b/tests/cts/permissionui/HelperAppOverlay/src/android/permissionui/cts/helper/overlay/OverlayActivity.kt
new file mode 100644
index 000000000..0ac0fd027
--- /dev/null
+++ b/tests/cts/permissionui/HelperAppOverlay/src/android/permissionui/cts/helper/overlay/OverlayActivity.kt
@@ -0,0 +1,26 @@
+package android.permissionui.cts.helper.overlay
+
+import android.app.Activity
+import android.os.Bundle
+import android.view.ViewGroup
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.view.WindowManager
+import android.widget.LinearLayout
+import android.widget.TextView
+
+class OverlayActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val mainLayout = LinearLayout(this)
+ mainLayout.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ val textView = TextView(this)
+
+ textView.text = "Find me!"
+ mainLayout.addView(textView)
+
+ val windowParams = WindowManager.LayoutParams()
+ windowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+ windowManager.addView(mainLayout, windowParams)
+ }
+}
diff --git a/tests/cts/permissionui/ImplicitUserSelectStorageApp/Android.bp b/tests/cts/permissionui/ImplicitUserSelectStorageApp/Android.bp
new file mode 100644
index 000000000..c341125fd
--- /dev/null
+++ b/tests/cts/permissionui/ImplicitUserSelectStorageApp/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppImplicitUserSelectStorage",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ target_sdk_version: "34",
+ min_sdk_version: "34",
+}
diff --git a/tests/cts/permissionui/ImplicitUserSelectStorageApp/AndroidManifest.xml b/tests/cts/permissionui/ImplicitUserSelectStorageApp/AndroidManifest.xml
new file mode 100644
index 000000000..212bf1508
--- /dev/null
+++ b/tests/cts/permissionui/ImplicitUserSelectStorageApp/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+ <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+
+ <application>
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/MediaPermissionApp33WithStorage/Android.bp b/tests/cts/permissionui/MediaPermissionApp33WithStorage/Android.bp
new file mode 100644
index 000000000..77664c40b
--- /dev/null
+++ b/tests/cts/permissionui/MediaPermissionApp33WithStorage/Android.bp
@@ -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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsMediaPermissionApp33WithStorage",
+ min_sdk_version: "33",
+ target_sdk_version: "33",
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+}
diff --git a/tests/cts/permissionui/MediaPermissionApp33WithStorage/AndroidManifest.xml b/tests/cts/permissionui/MediaPermissionApp33WithStorage/AndroidManifest.xml
new file mode 100644
index 000000000..ae21d1612
--- /dev/null
+++ b/tests/cts/permissionui/MediaPermissionApp33WithStorage/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/OWNERS b/tests/cts/permissionui/OWNERS
new file mode 100644
index 000000000..01fbb4851
--- /dev/null
+++ b/tests/cts/permissionui/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
+
diff --git a/tests/cts/permissionui/PermissionPolicyApp25/Android.bp b/tests/cts/permissionui/PermissionPolicyApp25/Android.bp
new file mode 100644
index 000000000..d3f88954c
--- /dev/null
+++ b/tests/cts/permissionui/PermissionPolicyApp25/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2017 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsPermissionPolicyApp25",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "25",
+}
diff --git a/tests/cts/permissionui/PermissionPolicyApp25/AndroidManifest.xml b/tests/cts/permissionui/PermissionPolicyApp25/AndroidManifest.xml
new file mode 100644
index 000000000..531ea47ac
--- /dev/null
+++ b/tests/cts/permissionui/PermissionPolicyApp25/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.permissionpolicy">
+
+ <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="25" />
+
+ <application>
+ <activity android:name=".TestProtectionFlagsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/PermissionPolicyApp25/src/android/permissionui/cts/permissionpolicy/TestProtectionFlagsActivity.kt b/tests/cts/permissionui/PermissionPolicyApp25/src/android/permissionui/cts/permissionpolicy/TestProtectionFlagsActivity.kt
new file mode 100644
index 000000000..35e61d0c2
--- /dev/null
+++ b/tests/cts/permissionui/PermissionPolicyApp25/src/android/permissionui/cts/permissionpolicy/TestProtectionFlagsActivity.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 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.permissionui.cts.permissionpolicy
+
+import android.app.Activity
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.PermissionInfo
+import android.os.Bundle
+
+/**
+ * An activity that can test platform permission protection flags.
+ */
+class TestProtectionFlagsActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setResult(
+ RESULT_OK, Intent().apply {
+ putExtra("$packageName.ERROR_MESSAGE", getProtectionFlagsErrorMessage())
+ }
+ )
+ finish()
+ }
+
+ private fun getProtectionFlagsErrorMessage(): String {
+ val packageInfo = packageManager.getPackageInfo("android", PackageManager.GET_PERMISSIONS)
+ val errorMessageBuilder = StringBuilder()
+ for (declaredPermissionInfo in packageInfo.permissions ?: emptyArray()) {
+ val permissionInfo = packageManager.getPermissionInfo(declaredPermissionInfo.name, 0)
+ val protection = permissionInfo.protection and (
+ PermissionInfo.PROTECTION_NORMAL
+ or PermissionInfo.PROTECTION_DANGEROUS
+ or PermissionInfo.PROTECTION_SIGNATURE
+ or PermissionInfo.PROTECTION_INTERNAL
+ )
+ val protectionFlags = permissionInfo.protectionLevel and protection.inv()
+ if ((protection == PermissionInfo.PROTECTION_NORMAL ||
+ protection == PermissionInfo.PROTECTION_DANGEROUS) && protectionFlags != 0) {
+ errorMessageBuilder.apply {
+ if (isNotEmpty()) {
+ append("\n")
+ }
+ append("Cannot add protection flags ${protectionFlagsToString(protectionFlags)
+ } to a ${protectionToString(protection)} protection permission: ${
+ permissionInfo.name}")
+ }
+ }
+ }
+ return errorMessageBuilder.toString()
+ }
+
+ private fun protectionToString(protection: Int): String =
+ when (protection) {
+ PermissionInfo.PROTECTION_NORMAL -> "normal"
+ PermissionInfo.PROTECTION_DANGEROUS -> "dangerous"
+ PermissionInfo.PROTECTION_SIGNATURE -> "signature"
+ PermissionInfo.PROTECTION_INTERNAL -> "internal"
+ else -> Integer.toHexString(protection)
+ }
+
+ private fun protectionFlagsToString(protectionFlags: Int): String {
+ var unknownProtectionFlags = protectionFlags
+ val stringBuilder = StringBuilder()
+ val appendProtectionFlag = { protectionFlag: Int, protectionFlagString: String ->
+ if (unknownProtectionFlags and protectionFlag == protectionFlag) {
+ stringBuilder.apply {
+ if (isNotEmpty()) {
+ append("|")
+ }
+ append(protectionFlagString)
+ }
+ unknownProtectionFlags = unknownProtectionFlags and protectionFlag.inv()
+ }
+ }
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_PRIVILEGED, "privileged")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_DEVELOPMENT, "development")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_APPOP, "appop")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_PRE23, "pre23")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_INSTALLER, "installer")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_VERIFIER, "verifier")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_PREINSTALLED, "preinstalled")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_SETUP, "setup")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_INSTANT, "instant")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY, "runtimeOnly")
+ appendProtectionFlag(PermissionInfo.PROTECTION_FLAG_ROLE, "role")
+ if (unknownProtectionFlags != 0) {
+ appendProtectionFlag(
+ unknownProtectionFlags, Integer.toHexString(unknownProtectionFlags)
+ )
+ }
+ return stringBuilder.toString()
+ }
+}
diff --git a/tests/cts/permissionui/StorageApp33/Android.bp b/tests/cts/permissionui/StorageApp33/Android.bp
new file mode 100644
index 000000000..35c79fada
--- /dev/null
+++ b/tests/cts/permissionui/StorageApp33/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppStorage33",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ target_sdk_version: "33",
+ min_sdk_version: "33",
+}
diff --git a/tests/cts/permissionui/StorageApp33/AndroidManifest.xml b/tests/cts/permissionui/StorageApp33/AndroidManifest.xml
new file mode 100644
index 000000000..212bf1508
--- /dev/null
+++ b/tests/cts/permissionui/StorageApp33/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+ <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+
+ <application>
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/TEST_MAPPING b/tests/cts/permissionui/TEST_MAPPING
new file mode 100644
index 000000000..c703c539d
--- /dev/null
+++ b/tests/cts/permissionui/TEST_MAPPING
@@ -0,0 +1,32 @@
+{
+ "presubmit-large": [
+ {
+ "name": "CtsPermissionUiTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "mainline-presubmit": [
+ {
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsPermissionUiTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsPermissionUiTestCases[com.google.android.permission.apex]"
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/cts/permissionui/UsePermissionApp22/Android.bp b/tests/cts/permissionui/UsePermissionApp22/Android.bp
new file mode 100644
index 000000000..dcb04f6a4
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2015 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp22",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "22",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp22/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp22/AndroidManifest.xml
new file mode 100644
index 000000000..6a8bb1fd8
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22/AndroidManifest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <!-- Make sure permission code can handle invalid permissions -->
+ <uses-permission android:name="android.permissionui.cts.usepermission.INVALID_PERMISSION_NAME" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <!-- Contacts -->
+ <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+
+ <!-- Calendar -->
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.READ_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
+ <uses-permission android:name="android.permission.RECEIVE_MMS" />
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
+
+ <!-- Storage -->
+ <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <!-- Location -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.CALL_PHONE" />
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+ <uses-permission android:name="android.permission.USE_SIP" />
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <!-- Camera -->
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <!-- Body Sensors -->
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp22CalendarOnly/Android.bp b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/Android.bp
new file mode 100644
index 000000000..26ff13566
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2015 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp22CalendarOnly",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "22",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp22CalendarOnly/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/AndroidManifest.xml
new file mode 100644
index 000000000..0610562b0
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <!-- Calendar -->
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ <activity android:name=".StartCheckPermissionServiceActivity" android:exported="true" />
+ <service android:name=".CheckPermissionService" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/CheckPermissionService.kt b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/CheckPermissionService.kt
new file mode 100644
index 000000000..635462470
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/CheckPermissionService.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 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.permissionui.cts.usepermission
+
+import android.app.IntentService
+import android.content.Intent
+import android.os.ResultReceiver
+
+/**
+ * A service that can check if a permission is currently granted
+ */
+class CheckPermissionService : IntentService(CheckPermissionService::class.java.simpleName) {
+ companion object {
+ private const val TEST_PACKAGE_NAME = "android.permissionui.cts"
+ }
+
+ override fun onHandleIntent(intent: Intent?) {
+ val extras = intent!!.extras!!
+ // Load bundle with context of client package so ResultReceiver class can be resolved
+ val testContext = createPackageContext(
+ TEST_PACKAGE_NAME, CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY
+ )
+ extras.classLoader = testContext.classLoader
+ val result = extras.getParcelable<ResultReceiver>("$packageName.RESULT")!!
+ val permission = extras.getString("$packageName.PERMISSION")!!
+ result.send(checkSelfPermission(permission), null)
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/StartCheckPermissionServiceActivity.kt b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/StartCheckPermissionServiceActivity.kt
new file mode 100644
index 000000000..ebb4c2f12
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22CalendarOnly/src/android/permissionui/cts/usepermission/StartCheckPermissionServiceActivity.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+
+class StartCheckPermissionServiceActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ startService(Intent(this, CheckPermissionService::class.java).putExtras(intent))
+ finish()
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionApp22None/Android.bp b/tests/cts/permissionui/UsePermissionApp22None/Android.bp
new file mode 100644
index 000000000..7d43f46ef
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22None/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp22None",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "22",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp22None/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp22None/AndroidManifest.xml
new file mode 100644
index 000000000..8ee3094ea
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp22None/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="22" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp23/Android.bp b/tests/cts/permissionui/UsePermissionApp23/Android.bp
new file mode 100644
index 000000000..b98b2d3a3
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp23/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2015 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp23",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "23",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp23/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp23/AndroidManifest.xml
new file mode 100644
index 000000000..c1bb806a5
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp23/AndroidManifest.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <!-- Contacts -->
+ <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+ <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+
+ <!-- Calendar -->
+ <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+ <uses-permission android:name="android.permission.READ_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
+ <uses-permission android:name="android.permission.RECEIVE_MMS" />
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS" />
+
+ <!-- Storage -->
+ <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <!-- Location -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.CALL_PHONE" />
+ <uses-permission android:name="android.permission.READ_CALL_LOG" />
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+ <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+ <uses-permission android:name="android.permission.USE_SIP" />
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <!-- Camera -->
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <!-- Body Sensors -->
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp25/Android.bp b/tests/cts/permissionui/UsePermissionApp25/Android.bp
new file mode 100644
index 000000000..d16d2c486
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp25/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp25",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "25",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp25/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp25/AndroidManifest.xml
new file mode 100644
index 000000000..f97a6b329
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp25/AndroidManifest.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="25" android:targetSdkVersion="25" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <!-- Contacts -->
+ <!-- Deliberately request WRITE_CONTACTS but *not* READ_CONTACTS -->
+ <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+
+ <!-- Calendar -->
+ <uses-permission android:name="android.permission.READ_CALENDAR"/>
+ <uses-permission android:name="android.permission.WRITE_CALENDAR"/>
+
+ <!-- SMS -->
+ <uses-permission android:name="android.permission.SEND_SMS"/>
+ <uses-permission android:name="android.permission.RECEIVE_SMS"/>
+ <uses-permission android:name="android.permission.READ_SMS"/>
+ <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
+ <uses-permission android:name="android.permission.RECEIVE_MMS"/>
+ <uses-permission android:name="android.permission.READ_CELL_BROADCASTS"/>
+
+ <!-- Storage -->
+ <!-- Special case: WRITE_EXTERNAL_STORAGE implies READ_EXTERNAL_STORAGE -->
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+ <!-- Location -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+ <uses-permission android:name="android.permission.CALL_PHONE"/>
+ <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+ <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
+ <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"/>
+ <uses-permission android:name="android.permission.USE_SIP"/>
+ <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
+
+ <!-- Phone -->
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+
+ <!-- Camera -->
+ <uses-permission android:name="android.permission.CAMERA"/>
+
+ <!-- Body Sensors -->
+ <uses-permission android:name="android.permission.BODY_SENSORS"/>
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp26/Android.bp b/tests/cts/permissionui/UsePermissionApp26/Android.bp
new file mode 100644
index 000000000..d76163b3a
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp26/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp26",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "26",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp26/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp26/AndroidManifest.xml
new file mode 100644
index 000000000..4c29436cf
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp26/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="26" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp28/Android.bp b/tests/cts/permissionui/UsePermissionApp28/Android.bp
new file mode 100644
index 000000000..1f388fdc7
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp28/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp28",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "28",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp28/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp28/AndroidManifest.xml
new file mode 100644
index 000000000..98ede951f
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp28/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp29/Android.bp b/tests/cts/permissionui/UsePermissionApp29/Android.bp
new file mode 100644
index 000000000..8375b1e77
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp29/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp29",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "29",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp29/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp29/AndroidManifest.xml
new file mode 100644
index 000000000..f1ae6c9d8
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp29/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp30/Android.bp b/tests/cts/permissionui/UsePermissionApp30/Android.bp
new file mode 100644
index 000000000..c1b4b8a9f
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp30",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+
+ min_sdk_version: "30",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp30/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp30/AndroidManifest.xml
new file mode 100644
index 000000000..7266fc1b6
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBackground/Android.bp b/tests/cts/permissionui/UsePermissionApp30WithBackground/Android.bp
new file mode 100644
index 000000000..eeac4ff8b
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBackground/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp30WithBackground",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+
+ min_sdk_version: "30",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBackground/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp30WithBackground/AndroidManifest.xml
new file mode 100644
index 000000000..5949d08f2
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBackground/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <application>
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBackground/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt b/tests/cts/permissionui/UsePermissionApp30WithBackground/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
new file mode 100644
index 000000000..7d07826de
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBackground/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+
+class RequestPermissionsActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)")
+ return
+ }
+
+ val permissions = intent.getStringArrayExtra("$packageName.PERMISSIONS")!!
+ requestPermissions(permissions, 1)
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ setResult(RESULT_OK, Intent().apply {
+ putExtra("$packageName.PERMISSIONS", permissions)
+ putExtra("$packageName.GRANT_RESULTS", grantResults)
+ })
+ finish()
+ }
+
+ companion object {
+ private val TAG = RequestPermissionsActivity::class.simpleName
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBluetooth/Android.bp b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/Android.bp
new file mode 100644
index 000000000..d92ce5732
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp30WithBluetooth",
+ srcs: [
+ "src/**/*.kt"
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ ],
+ certificate: ":cts-testkey2",
+
+ min_sdk_version: "30",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBluetooth/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/AndroidManifest.xml
new file mode 100644
index 000000000..4d01e99c5
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+
+ <application>
+ <provider
+ android:name=".AccessBluetoothOnCommand"
+ android:authorities="android.permissionui.cts.usepermission.AccessBluetoothOnCommand"
+ android:exported="true" />
+ </application>
+
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp30WithBluetooth/src/android/permissionui/cts/usepermission/AccessBluetoothOnCommand.kt b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/src/android/permissionui/cts/usepermission/AccessBluetoothOnCommand.kt
new file mode 100644
index 000000000..107dd4469
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp30WithBluetooth/src/android/permissionui/cts/usepermission/AccessBluetoothOnCommand.kt
@@ -0,0 +1,145 @@
+/*
+ * 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.permissionui.cts.usepermission
+
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanResult
+import android.content.ContentProvider
+import android.content.ContentValues
+import android.content.Intent
+import android.database.Cursor
+import android.net.Uri
+import android.os.Bundle
+import android.os.SystemClock
+import android.util.Base64
+import android.util.Log
+import java.util.concurrent.ConcurrentHashMap
+import java.util.concurrent.atomic.AtomicInteger
+
+private const val LOG_TAG = "AccessBluetoothOnCommand"
+
+class AccessBluetoothOnCommand : ContentProvider() {
+
+ private enum class Result {
+ UNKNOWN, ERROR, EXCEPTION, EMPTY, FILTERED, FULL
+ }
+
+ override fun call(authority: String, method: String, arg: String?, extras: Bundle?): Bundle? {
+ Log.v(LOG_TAG, "call() - start")
+ val res = Bundle()
+
+ var scanner: BluetoothLeScanner? = null
+ var scanCallback: ScanCallback? = null
+
+ try {
+
+ scanner = context!!.getSystemService(BluetoothManager::class.java)
+ ?.adapter!!.bluetoothLeScanner
+
+ val observedScans: MutableSet<String> = ConcurrentHashMap.newKeySet()
+ val observedErrorCode = AtomicInteger(0)
+
+ scanCallback = object : ScanCallback() {
+ override fun onScanResult(callbackType: Int, result: ScanResult) {
+ Log.v(LOG_TAG, "onScanResult() - result = $result")
+ observedScans.add(Base64.encodeToString(result.scanRecord!!.bytes, 0))
+ }
+
+ override fun onBatchScanResults(results: List<ScanResult>) {
+ Log.v(LOG_TAG, "onBatchScanResults() - results.size = ${results.size}")
+ for (result in results) {
+ onScanResult(0, result)
+ }
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ Log.e(LOG_TAG, "onScanFailed() - errorCode = $errorCode")
+ observedErrorCode.set(errorCode)
+ }
+ }
+
+ Log.v(LOG_TAG, "call() - startScan...")
+ scanner.startScan(scanCallback)
+
+ // Wait a few seconds to figure out what we actually observed
+ Log.v(LOG_TAG, "call() - sleep...")
+ SystemClock.sleep(3000)
+
+ if (observedErrorCode.get() > 0) {
+ Log.v(LOG_TAG, "call() observed error: ${observedErrorCode.get()}")
+ res.putInt(Intent.EXTRA_INDEX, Result.ERROR.ordinal)
+ return res
+ }
+ Log.v(LOG_TAG, "call() - (scanCount=${observedScans.size})")
+
+ when (observedScans.size) {
+ 0 -> res.putInt(Intent.EXTRA_INDEX, Result.EMPTY.ordinal)
+ 1 -> res.putInt(Intent.EXTRA_INDEX, Result.FILTERED.ordinal)
+ 5 -> res.putInt(Intent.EXTRA_INDEX, Result.FULL.ordinal)
+ else -> res.putInt(Intent.EXTRA_INDEX, Result.UNKNOWN.ordinal)
+ }
+ } catch (t: Throwable) {
+ Log.e(LOG_TAG, "call() - EXCEPTION", t)
+ res.putInt(Intent.EXTRA_INDEX, Result.EXCEPTION.ordinal)
+ } finally {
+ try {
+ Log.v(LOG_TAG, "call() - finally - stopScan...")
+ scanner!!.stopScan(scanCallback)
+ } catch (e: Exception) {
+ Log.e(LOG_TAG, "call() - finally - EXCEPTION", e)
+ }
+ }
+ Log.v(LOG_TAG, "call() - end")
+ return res
+ }
+
+ override fun onCreate(): Boolean {
+ return true
+ }
+
+ override fun query(
+ uri: Uri,
+ projection: Array<String>?,
+ selection: String?,
+ selectionArgs: Array<String>?,
+ sortOrder: String?
+ ): Cursor? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getType(uri: Uri): String? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun insert(uri: Uri, values: ContentValues?): Uri? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
+ throw UnsupportedOperationException()
+ }
+
+ override fun update(
+ uri: Uri,
+ values: ContentValues?,
+ selection: String?,
+ selectionArgs: Array<String>?
+ ): Int {
+ throw UnsupportedOperationException()
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionApp31/Android.bp b/tests/cts/permissionui/UsePermissionApp31/Android.bp
new file mode 100644
index 000000000..4424d95fe
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp31/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp31",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ target_sdk_version: "31",
+ min_sdk_version: "31",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp31/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp31/AndroidManifest.xml
new file mode 100644
index 000000000..31d025ea0
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp31/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?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.
+ -->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+ <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionApp32/Android.bp b/tests/cts/permissionui/UsePermissionApp32/Android.bp
new file mode 100644
index 000000000..874af0e06
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp32/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionApp32",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+
+ min_sdk_version: "32",
+ target_sdk_version: "32",
+}
diff --git a/tests/cts/permissionui/UsePermissionApp32/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionApp32/AndroidManifest.xml
new file mode 100644
index 000000000..923139e66
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionApp32/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?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.
+ -->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <application>
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/Android.bp b/tests/cts/permissionui/UsePermissionAppLatest/Android.bp
new file mode 100644
index 000000000..c9e9f8fb0
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatest/Android.bp
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2017 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "CtsUsePermissionAppSrc",
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppLatest",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml
new file mode 100644
index 000000000..49e45fc01
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <!-- Request two different permissions within the same group -->
+ <uses-permission android:name="android.permission.SEND_SMS" />
+ <uses-permission android:name="android.permission.RECEIVE_SMS" />
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.BODY_SENSORS" />
+
+ <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
+ <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
+ <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
+
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ <activity-alias
+ android:name=".ViewPermissionUsageActivity"
+ android:exported="true"
+ android:permission="android.permission.START_VIEW_PERMISSION_USAGE"
+ android:targetActivity=".FinishOnCreateActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
+ </intent-filter>
+ </activity-alias>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/CheckCalendarAccessActivity.kt b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/CheckCalendarAccessActivity.kt
new file mode 100644
index 000000000..41edbd3f1
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/CheckCalendarAccessActivity.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.ContentValues
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.provider.CalendarContract
+
+/**
+ * An activity that can check calendar access.
+ */
+class CheckCalendarAccessActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val supportsRuntimePermissions = applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M
+ val hasAccess: Boolean
+ val uri = try {
+ contentResolver.insert(
+ CalendarContract.Calendars.CONTENT_URI, ContentValues().apply {
+ put(CalendarContract.Calendars.NAME, "cts" + System.nanoTime())
+ put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "cts")
+ put(CalendarContract.Calendars.CALENDAR_COLOR, 0xffff0000)
+ }
+ )!!
+ } catch (e: SecurityException) {
+ null
+ }
+ hasAccess = if (uri != null) {
+ val count = contentResolver.query(uri, null, null, null).use { it!!.count }
+ if (supportsRuntimePermissions) {
+ assert(count == 1)
+ true
+ } else {
+ // Without access we're handed back a "fake" Uri that doesn't contain
+ // any of the data we tried persisting
+ assert(count == 0 || count == 1)
+ count == 1
+ }
+ } else {
+ assert(supportsRuntimePermissions)
+ try {
+ contentResolver.query(CalendarContract.Calendars.CONTENT_URI, null, null, null)
+ .use {}
+ error("Expected SecurityException")
+ } catch (e: SecurityException) {}
+ false
+ }
+ setResult(RESULT_OK, Intent().apply { putExtra("$packageName.HAS_ACCESS", hasAccess) })
+ finish()
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/FinishOnCreateActivity.kt b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/FinishOnCreateActivity.kt
new file mode 100644
index 000000000..693a8c8f9
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/FinishOnCreateActivity.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.os.Bundle
+
+class FinishOnCreateActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setResult(RESULT_OK)
+ finish()
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
new file mode 100644
index 000000000..3eea77340
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatest/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import com.android.modules.utils.build.SdkLevel
+
+class RequestPermissionsActivity : Activity() {
+
+ private var shouldAskTwice = false
+ private var timesAsked = 0
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)")
+ return
+ }
+
+ val permissions = intent.getStringArrayExtra("$packageName.PERMISSIONS")!!
+ shouldAskTwice = intent.getBooleanExtra("$packageName.ASK_TWICE", false)
+ if (SdkLevel.isAtLeastV()) {
+ // TODO: make deviceId dynamic
+ requestPermissions(permissions, 1, Context.DEVICE_ID_DEFAULT)
+ } else {
+ requestPermissions(permissions, 1)
+ }
+ timesAsked = 1
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray
+ ) {
+ handleResult(permissions, grantResults)
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray,
+ deviceId: Int
+ ) {
+ handleResult(permissions, grantResults, deviceId)
+ }
+
+ private fun handleResult(
+ permissions: Array<out String>,
+ grantResults: IntArray,
+ deviceId: Int? = null
+ ) {
+ if (shouldAskTwice && timesAsked < 2) {
+ requestPermissions(permissions, 1)
+ timesAsked += 1
+ return
+ }
+
+ setResult(
+ RESULT_OK,
+ Intent().apply {
+ putExtra("$packageName.PERMISSIONS", permissions)
+ putExtra("$packageName.GRANT_RESULTS", grantResults)
+ if (deviceId != null) {
+ putExtra("$packageName.DEVICE_ID", deviceId)
+ }
+ }
+ )
+ finish()
+ }
+
+ companion object {
+ private val TAG = RequestPermissionsActivity::class.simpleName
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLatestNone/Android.bp b/tests/cts/permissionui/UsePermissionAppLatestNone/Android.bp
new file mode 100644
index 000000000..cbc934eef
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatestNone/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppLatestNone",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLatestNone/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppLatestNone/AndroidManifest.xml
new file mode 100644
index 000000000..49103769e
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLatestNone/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <application>
+ <activity android:name=".CheckCalendarAccessActivity" android:exported="true" />
+ <activity android:name=".FinishOnCreateActivity" android:exported="true" />
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionAppLocationProvider/Android.bp b/tests/cts/permissionui/UsePermissionAppLocationProvider/Android.bp
new file mode 100644
index 000000000..a2cd88d4e
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLocationProvider/Android.bp
@@ -0,0 +1,31 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAccessMicrophoneAppLocationProvider",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "31",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+} \ No newline at end of file
diff --git a/tests/cts/permissionui/UsePermissionAppLocationProvider/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppLocationProvider/AndroidManifest.xml
new file mode 100644
index 000000000..03edc78a2
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLocationProvider/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.accessmicrophoneapplocationprovider">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <attribution
+ android:label="@string/attribution_label"
+ android:tag="test.tag" />
+
+ <application
+ android:attributionsAreUserVisible="true"
+ android:label="LocationProviderWithMicApp">
+ <activity android:name=".AddLocationProviderActivity" android:exported="true" />
+ <activity android:name=".UseMicrophoneActivity" android:exported="true"/>
+ </application>
+</manifest>
diff --git a/PermissionController/res/values-w764dp-v33/dimens.xml b/tests/cts/permissionui/UsePermissionAppLocationProvider/res/values/strings.xml
index 78b4675f2..9682d7f8a 100644
--- a/PermissionController/res/values-w764dp-v33/dimens.xml
+++ b/tests/cts/permissionui/UsePermissionAppLocationProvider/res/values/strings.xml
@@ -1,5 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
<!--
- ~ Copyright (C) 2022 The Android Open Source Project
+ ~ 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.
@@ -15,5 +17,5 @@
-->
<resources>
- <dimen name="sc_button_horizontal_padding">@dimen/sc_large_screen_button_padding</dimen>
+ <string name="attribution_label">Attribution Label</string>
</resources>
diff --git a/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/AddLocationProviderActivity.kt b/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/AddLocationProviderActivity.kt
new file mode 100644
index 000000000..e7977b459
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/AddLocationProviderActivity.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.permissionui.cts.accessmicrophoneapplocationprovider
+
+import android.app.Activity
+import android.location.Criteria
+import android.location.LocationManager
+import android.os.Bundle
+
+/**
+ * An activity that adds this package as a test location provider and uses microphone.
+ */
+class AddLocationProviderActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val attrContext = createAttributionContext("test.tag")
+ val locationManager = attrContext.getSystemService(LocationManager::class.java)!!
+ locationManager.addTestProvider(
+ packageName, false, false, false, false, false, false, false, Criteria.POWER_LOW,
+ Criteria.ACCURACY_COARSE
+ )
+
+ setResult(RESULT_OK)
+ finish()
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/UseMicrophoneActivity.kt b/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/UseMicrophoneActivity.kt
new file mode 100644
index 000000000..e605f6eff
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppLocationProvider/src/android/permissionui/cts/accessmicrophoneapplocationprovider/UseMicrophoneActivity.kt
@@ -0,0 +1,67 @@
+/*
+ * 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.permissionui.cts.accessmicrophoneapplocationprovider
+
+import android.app.Activity
+import android.content.Context
+import android.media.AudioFormat
+import android.media.AudioRecord
+import android.media.MediaRecorder
+import android.os.Bundle
+import android.os.Handler
+
+private const val USE_DURATION_MS = 10000L
+private const val SAMPLE_RATE_HZ = 44100
+
+/**
+ * An activity that uses microphone.
+ */
+class UseMicrophoneActivity : Activity() {
+ private var recorder: AudioRecord? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val attrContext = createAttributionContext("test.tag")
+ useMic(attrContext)
+ setResult(RESULT_OK)
+ finish()
+ }
+
+ override fun finish() {
+ recorder?.stop()
+ recorder = null
+ super.finish()
+ }
+
+ override fun onStop() {
+ super.onStop()
+ finish()
+ }
+
+ private fun useMic(context: Context) {
+ recorder = AudioRecord.Builder()
+ .setAudioSource(MediaRecorder.AudioSource.MIC)
+ .setAudioFormat(AudioFormat.Builder()
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setSampleRate(SAMPLE_RATE_HZ)
+ .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
+ .build())
+ .setContext(context)
+ .build()
+ recorder?.startRecording()
+ Handler().postDelayed({ finish() }, USE_DURATION_MS)
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppStreaming/Android.bp b/tests/cts/permissionui/UsePermissionAppStreaming/Android.bp
new file mode 100644
index 000000000..6de63501e
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppStreaming/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppStreaming",
+ srcs: [
+ ":CtsUsePermissionAppSrc",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ "compatibility-device-util-axt",
+ ],
+ certificate: ":cts-testkey2",
+ min_sdk_version: "34",
+ target_sdk_version: "34",
+}
diff --git a/tests/cts/permissionui/UsePermissionAppStreaming/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppStreaming/AndroidManifest.xml
new file mode 100644
index 000000000..b48b2b1be
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppStreaming/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <application>
+ <activity android:name=".RequestPermissionActivity" android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionAppStreaming/src/android/permissionui/cts/usepermission/RequestPermissionActivity.kt b/tests/cts/permissionui/UsePermissionAppStreaming/src/android/permissionui/cts/usepermission/RequestPermissionActivity.kt
new file mode 100644
index 000000000..d507870c5
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppStreaming/src/android/permissionui/cts/usepermission/RequestPermissionActivity.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts.usepermission
+
+import android.Manifest
+import android.app.Activity
+import android.os.Bundle
+
+class RequestPermissionActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ requestPermissions(arrayOf(Manifest.permission.CAMERA), 1001)
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/Android.bp b/tests/cts/permissionui/UsePermissionAppWithOverlay/Android.bp
new file mode 100644
index 000000000..6ae324577
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2020 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsUsePermissionAppWithOverlay",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ resource_dirs: [
+ "res",
+ ],
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+ certificate: ":cts-testkey2",
+}
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppWithOverlay/AndroidManifest.xml
new file mode 100644
index 000000000..037ff548f
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission">
+
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <application>
+ <activity android:name=".RequestPermissionsActivity" android:exported="true" />
+ <activity android:name=".OverlayActivity"
+ android:theme="@style/OverlayTheme" />
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/res/drawable/border.xml b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/drawable/border.xml
new file mode 100644
index 000000000..1e637be61
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/drawable/border.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#FFFFFF" />
+ <corners
+ android:radius="4dp"/>
+ <stroke
+ android:width="4dp"
+ android:color="@android:color/black" />
+</shape>
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/res/layout/overlay_activity.xml b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/layout/overlay_activity.xml
new file mode 100644
index 000000000..ea355f761
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/layout/overlay_activity.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2020 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/overlay"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/border"
+ android:padding="8dp" >
+
+ <View android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <TextView android:id="@+id/overlay_description"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/black"
+ android:text="@string/app_description" />
+</LinearLayout> \ No newline at end of file
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/strings.xml b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/strings.xml
new file mode 100644
index 000000000..ca0b4ffc1
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2020 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>
+ <string name="app_description">This activity attempts to tapjack the activity below.\nAny security sensitive controls below should not respond to taps as long as this activity is visible.</string>
+</resources> \ No newline at end of file
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/styles.xml b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/styles.xml
new file mode 100644
index 000000000..880d94037
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/res/values/styles.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2020 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>
+ <style name="OverlayTheme" parent="android:Theme.Dialog">
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ </style>
+</resources>
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/OverlayActivity.kt b/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/OverlayActivity.kt
new file mode 100644
index 000000000..518b51e66
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/OverlayActivity.kt
@@ -0,0 +1,55 @@
+package android.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import android.view.Gravity
+import android.view.WindowManager
+
+class OverlayActivity : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.overlay_activity)
+ val params = window.attributes
+ params.flags = (WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
+
+ if (!intent.getBooleanExtra(EXTRA_FULL_OVERLAY, true)) {
+ params.gravity = Gravity.LEFT or Gravity.TOP
+ val left = intent.getIntExtra(OVERLAY_LEFT, params.x)
+ val top = intent.getIntExtra(OVERLAY_TOP, params.y)
+ val right = intent.getIntExtra(OVERLAY_RIGHT, params.x + params.width)
+ val bottom = intent.getIntExtra(OVERLAY_BOTTOM, top + 1)
+ params.x = left
+ params.y = top
+ params.width = right - left
+ params.height = bottom - top
+ }
+
+ registerReceiver(object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ if (intent?.action != RequestPermissionsActivity.ACTION_HIDE_OVERLAY) {
+ return
+ }
+
+ finish()
+ }
+ }, IntentFilter(RequestPermissionsActivity.ACTION_HIDE_OVERLAY), RECEIVER_EXPORTED)
+ }
+
+ companion object {
+ const val EXTRA_FULL_OVERLAY = "android.permissionui.cts.usepermission.extra.FULL_OVERLAY"
+
+ const val OVERLAY_LEFT = "android.permissionui.cts.usepermission.extra.OVERLAY_LEFT"
+ const val OVERLAY_TOP = "android.permissionui.cts.usepermission.extra.OVERLAY_TOP"
+ const val OVERLAY_RIGHT = "android.permissionui.cts.usepermission.extra.OVERLAY_RIGHT"
+ const val OVERLAY_BOTTOM = "android.permissionui.cts.usepermission.extra.OVERLAY_BOTTOM"
+ }
+}
diff --git a/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt b/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
new file mode 100644
index 000000000..add0df19f
--- /dev/null
+++ b/tests/cts/permissionui/UsePermissionAppWithOverlay/src/android/permissionui/cts/usepermission/RequestPermissionsActivity.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts.usepermission
+
+import android.app.Activity
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Bundle
+import android.os.Handler
+import android.util.Log
+
+class RequestPermissionsActivity : Activity() {
+
+ var paused = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)")
+ return
+ }
+
+ registerReceiver(object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ if (intent?.action != ACTION_SHOW_OVERLAY) {
+ return
+ }
+
+ startActivity(intent
+ .setAction(null)
+ .setComponent(ComponentName(context!!, OverlayActivity::class.java))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+ }
+ }, IntentFilter(ACTION_SHOW_OVERLAY), RECEIVER_EXPORTED)
+ Handler(mainLooper).post(this::eventuallyRequestPermission)
+ }
+
+ /**
+ * Keep trying to requestPermissions until the dialog shows. It may fail the first few times
+ * due to rapid install/uninstall tests do
+ */
+ private fun eventuallyRequestPermission() {
+ if (!paused) {
+ val permissions = intent.getStringArrayExtra("$packageName.PERMISSIONS")!!
+ requestPermissions(permissions, 1)
+ Handler(mainLooper).postDelayed(this::eventuallyRequestPermission, 200)
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<out String>,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+
+ setResult(RESULT_OK, Intent().apply {
+ putExtra("$packageName.PERMISSIONS", permissions)
+ putExtra("$packageName.GRANT_RESULTS", grantResults)
+ })
+ finish()
+ }
+
+ override fun onPause() {
+ paused = true
+ super.onPause()
+ }
+
+ override fun onResume() {
+ paused = false
+ super.onResume()
+ }
+
+ companion object {
+ const val ACTION_SHOW_OVERLAY = "android.permissionui.cts.usepermission.ACTION_SHOW_OVERLAY"
+ const val ACTION_HIDE_OVERLAY = "android.permissionui.cts.usepermission.ACTION_HIDE_OVERLAY"
+ private val TAG = RequestPermissionsActivity::class.simpleName
+ }
+}
diff --git a/tests/cts/permissionui/res/raw/lg_g4_iso_800_jpg.jpg b/tests/cts/permissionui/res/raw/lg_g4_iso_800_jpg.jpg
new file mode 100644
index 000000000..d26419604
--- /dev/null
+++ b/tests/cts/permissionui/res/raw/lg_g4_iso_800_jpg.jpg
Binary files differ
diff --git a/tests/cts/permissionui/res/raw/test_video.mp4 b/tests/cts/permissionui/res/raw/test_video.mp4
new file mode 100644
index 000000000..ab95ac07d
--- /dev/null
+++ b/tests/cts/permissionui/res/raw/test_video.mp4
Binary files differ
diff --git a/PermissionController/res/values-w764dp-v34/dimens.xml b/tests/cts/permissionui/res/values-en-rGB/strings.xml
index cb336fc3e..7c98df768 100644..100755
--- a/PermissionController/res/values-w764dp-v34/dimens.xml
+++ b/tests/cts/permissionui/res/values-en-rGB/strings.xml
@@ -1,5 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
<!--
- ~ Copyright (C) 2022 The Android Open Source Project
+ ~ Copyright (C) 2017 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.
@@ -15,5 +17,5 @@
-->
<resources>
- <dimen name="sc_action_button_list_margin">@dimen/sc_spacing_large</dimen>
+ <string name="permissions">Permission</string>
</resources>
diff --git a/tests/cts/permissionui/res/values/strings.xml b/tests/cts/permissionui/res/values/strings.xml
new file mode 100755
index 000000000..b2f8e3dac
--- /dev/null
+++ b/tests/cts/permissionui/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2017 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>
+ <string name="permissions">Permissions</string>
+ <string name="allow_foreground">Allow only while using the app</string>
+ <string name="allow_media_storage">Allow access to media only</string>
+ <string name="allow_external_storage">Allow management of all files</string>
+ <string name="car_mic_privacy_chip_id">com.android.systemui:id/mic_privacy_chip</string>
+ <string name="car_camera_privacy_chip_id">com.android.systemui:id/camera_privacy_chip</string>
+ <string name="test_accessibility_service">TestService1</string>
+ <string name="test_accessibility_service_2">TestService2</string>
+</resources>
diff --git a/tests/cts/permissionui/res/xml/test_accessibilityservice.xml b/tests/cts/permissionui/res/xml/test_accessibilityservice.xml
new file mode 100644
index 000000000..fa87e2e0f
--- /dev/null
+++ b/tests/cts/permissionui/res/xml/test_accessibilityservice.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accessibilityEventTypes="typeAllMask"
+ android:accessibilityFeedbackType="feedbackGeneric"
+ android:canRetrieveWindowContent="true"
+ android:accessibilityFlags="flagDefault"
+ android:notificationTimeout="0" />
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt
new file mode 100644
index 000000000..5feb48b42
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppDataSharingUpdatesTest.kt
@@ -0,0 +1,542 @@
+/*
+ * 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.permissionui.cts
+
+import android.app.ActivityManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_OTHER
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_STORE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED
+import android.os.Build
+import android.os.PersistableBundle
+import android.permission.cts.PermissionUtils
+import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingAds
+import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingNoAds
+import android.permissionui.cts.AppMetadata.createAppMetadataWithNoSharing
+import android.provider.DeviceConfig
+import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
+import android.util.Log
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts
+import com.android.modules.utils.build.SdkLevel
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+/** Tests the UI that displays information about apps' updates to their data sharing policies. */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class AppDataSharingUpdatesTest : BaseUsePermissionTest() {
+ // TODO(b/263838456): Add tests for personal and work profile.
+
+ private var activityManager: ActivityManager? = null
+
+ @get:Rule
+ val deviceConfigSafetyLabelChangeNotificationsEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED,
+ true.toString())
+
+ @get:Rule
+ val deviceConfigDataSharingUpdatesPeriod =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS,
+ "600000")
+
+ /**
+ * This rule serves to limit the max number of safety labels that can be persisted, so that
+ * repeated tests don't overwhelm the disk storage on the device.
+ */
+ @get:Rule
+ val deviceConfigMaxSafetyLabelsPersistedPerApp =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP,
+ "2")
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(
+ "Data sharing updates page is only available on U+", SdkLevel.isAtLeastU())
+ Assume.assumeFalse(isAutomotive)
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+
+ PermissionUtils.clearAppState(context.packageManager.permissionControllerPackageName)
+ waitForBroadcasts()
+ activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedCoarseLocation_noSharingToNoAdsSharing_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedFineLocation_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedBackgroundLocation_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantBackgroundLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_noSharingToAdsSharing_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingAds())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES_FOR_ADS), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_noAdsSharingToAdsSharing_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingNoAds(),
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingAds())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES_FOR_ADS), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_adsSharingToNoAdsSharing_showsNoUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingAds(),
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_noAdsSharingToNoSharing_showsNoUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingNoAds(),
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_adsSharingToNoSharing_showsNoUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingAds(),
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ grantCoarseLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Ignore("b/282063206")
+ @Test
+ fun clickLearnMore_opensHelpCenter() {
+ Assume.assumeFalse(getPermissionControllerResString(HELP_CENTER_URL_ID).isNullOrEmpty())
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(LEARN_ABOUT_DATA_SHARING), true)
+
+ clickAndWaitForWindowTransition(By.textContains(LEARN_ABOUT_DATA_SHARING))
+
+ eventually({assertHelpCenterLinkClickSuccessful()}, HELP_CENTER_TIMEOUT_MILLIS)
+ } finally {
+ pressBack()
+ pressBack()
+ }
+ }
+
+ @Test
+ fun noHelpCenterLinkAvailable_noHelpCenterClickAction() {
+ Assume.assumeTrue(getPermissionControllerResString(HELP_CENTER_URL_ID).isNullOrEmpty())
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(LEARN_ABOUT_DATA_SHARING), false)
+ } finally {
+ pressBack()
+ pressBack()
+ }
+ }
+
+ @Test
+ fun clickUpdate_opensAppLocationPermissionPage() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(UPDATES_IN_LAST_30_DAYS), true)
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+
+ clickAndWaitForWindowTransition(By.textContains(APP_PACKAGE_NAME_SUBSTRING))
+
+ findView(By.descContains(LOCATION_PERMISSION), true)
+ findView(By.textContains(APP_PACKAGE_NAME), true)
+ } finally {
+ pressBack()
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppNotGrantedLocation_showsNoUpdates() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithNoSharing(), waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_noMetadata_showsNoUpdates() {
+ installPackageWithoutInstallSource(APP_APK_PATH_31)
+ waitForBroadcasts()
+ installPackageWithoutInstallSource(APP_APK_PATH_31)
+ waitForBroadcasts()
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_featureDisabled_doesNotOpenDataSharingUpdatesPage() {
+ setDeviceConfigPrivacyProperty(SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false.toString())
+
+ startAppDataSharingUpdatesActivity()
+
+ findView(By.descContains(DATA_SHARING_UPDATES), false)
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedFineLocation_packageSourceUnspecified_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_UNSPECIFIED,
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_UNSPECIFIED)
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceOther_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_OTHER,
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(), PACKAGE_SOURCE_OTHER)
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceStore_showsUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_STORE,
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(), PACKAGE_SOURCE_STORE)
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertUpdatesPresent()
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(NOW_SHARED_WITH_THIRD_PARTIES), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceLocalFile_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_LOCAL_FILE,
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(), PACKAGE_SOURCE_LOCAL_FILE)
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ @Test
+ fun startActivityWithIntent_whenAppGrantedLocation_packageSourceDownloaded_doesntShowUpdate() {
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE,
+ waitTillBroadcastProcessed = true)
+ installAndWaitTillPackageAdded(
+ APP_APK_NAME_31,
+ createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE)
+ grantFineLocationPermission(APP_PACKAGE_NAME)
+
+ startAppDataSharingUpdatesActivity()
+
+ try {
+ assertNoUpdatesPresent()
+ } finally {
+ pressBack()
+ }
+ }
+
+ /** Installs an app and waits for the package added broadcast to be dispatched. */
+ private fun installAndWaitTillPackageAdded(
+ apkPath: String,
+ appMetadata: PersistableBundle,
+ packageSource: Int? = null,
+ waitTillBroadcastProcessed: Boolean = false
+ ) {
+ installPackageViaSession(apkPath, appMetadata, packageSource)
+ waitForBroadcasts()
+ // TODO(b/279455955): Investigate why this is necessary and remove if possible.
+ if (waitTillBroadcastProcessed) Thread.sleep(500)
+ }
+
+ private fun assertUpdatesPresent() {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_SUBTITLE), true)
+ findView(By.textContains(UPDATES_IN_LAST_30_DAYS), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_FOOTER_MESSAGE), true)
+ findView(By.textContains(LEARN_ABOUT_DATA_SHARING), shouldShowLearnMoreLink())
+ }
+
+ private fun assertNoUpdatesPresent() {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_SUBTITLE), true)
+ findView(By.textContains(DATA_SHARING_NO_UPDATES_MESSAGE), true)
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), false)
+ findView(By.textContains(UPDATES_IN_LAST_30_DAYS), false)
+ findView(By.textContains(DATA_SHARING_UPDATES_FOOTER_MESSAGE), true)
+ findView(By.textContains(LEARN_ABOUT_DATA_SHARING), shouldShowLearnMoreLink())
+ }
+
+ private fun grantFineLocationPermission(packageName: String) {
+ uiAutomation.grantRuntimePermission(
+ packageName, android.Manifest.permission.ACCESS_FINE_LOCATION)
+ }
+ private fun grantCoarseLocationPermission(packageName: String) {
+ uiAutomation.grantRuntimePermission(
+ packageName, android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ }
+ private fun grantBackgroundLocationPermission(packageName: String) {
+ uiAutomation.grantRuntimePermission(
+ packageName, android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)
+ }
+
+ private fun assertHelpCenterLinkClickSuccessful() {
+ runWithShellPermissionIdentity {
+ val runningTasks = activityManager!!.getRunningTasks(5)
+
+ Log.v(TAG, "# running tasks: ${runningTasks.size}")
+ assertFalse("Expected runningTasks to not be empty", runningTasks.isEmpty())
+
+ runningTasks.forEachIndexed { index, runningTaskInfo ->
+ Log.v(TAG, "task $index ${runningTaskInfo.baseIntent}")
+ }
+
+ val taskInfo = runningTasks[0]
+ val observedIntentAction = taskInfo.baseIntent.action
+ val observedIntentDataString = taskInfo.baseIntent.dataString
+ val observedIntentScheme: String? = taskInfo.baseIntent.scheme
+
+ Log.v(TAG, "task base intent: ${taskInfo.baseIntent}")
+ assertEquals("Unexpected intent action", Intent.ACTION_VIEW, observedIntentAction)
+
+ val expectedUrl = getPermissionControllerResString(HELP_CENTER_URL_ID)!!
+ assertFalse(observedIntentDataString.isNullOrEmpty())
+ assertTrue(observedIntentDataString?.startsWith(expectedUrl) ?: false)
+
+ assertFalse(observedIntentScheme.isNullOrEmpty())
+ assertEquals("https", observedIntentScheme)
+ }
+ }
+
+ private fun shouldShowLearnMoreLink(): Boolean {
+ return !getPermissionControllerResString(HELP_CENTER_URL_ID).isNullOrEmpty()
+ }
+
+ /** Companion object for [AppDataSharingUpdatesTest]. */
+ companion object {
+ private val TAG = AppDataSharingUpdatesTest::class.java.simpleName
+
+ private const val HELP_CENTER_URL_ID = "data_sharing_help_center_link"
+ private const val HELP_CENTER_TIMEOUT_MILLIS: Long = 20000
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppMetadata.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppMetadata.kt
new file mode 100644
index 000000000..9117e6205
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppMetadata.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.os.PersistableBundle
+
+/** Helper methods for creating test app metadata [PersistableBundle] */
+object AppMetadata {
+ /** Returns empty App Metadata [PersistableBundle] representation */
+ fun createEmptyAppMetadata(): PersistableBundle {
+ return PersistableBundle()
+ }
+
+ /** Returns valid App Metadata [PersistableBundle] representation */
+ fun createDefaultAppMetadata(): PersistableBundle {
+ val approximateLocationBundle =
+ PersistableBundle().apply { putIntArray(KEY_PURPOSES, (1..7).toList().toIntArray()) }
+
+ val locationBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(APPROX_LOCATION, approximateLocationBundle)
+ }
+
+ val dataSharedBundle =
+ PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
+
+ val dataLabelBundle =
+ PersistableBundle().apply { putPersistableBundle(KEY_DATA_SHARED, dataSharedBundle) }
+
+ val safetyLabelBundle =
+ PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION)
+ putPersistableBundle(KEY_DATA_LABELS, dataLabelBundle)
+ }
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, safetyLabelBundle)
+ }
+ }
+
+ /**
+ * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
+ * label name usage
+ */
+ fun createInvalidAppMetadata(): PersistableBundle {
+ val validAppMetaData = createDefaultAppMetadata()
+ val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_INVALID, validSafetyLabel)
+ }
+ }
+
+ /**
+ * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to no top
+ * level meta data version number.
+ */
+ fun createInvalidAppMetadataWithoutTopLevelVersion(): PersistableBundle {
+ val validAppMetaData = createDefaultAppMetadata()
+ val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
+
+ return PersistableBundle().apply {
+ putPersistableBundle(KEY_SAFETY_LABELS, validSafetyLabel)
+ }
+ }
+
+ /**
+ * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
+ * top level meta data version number.
+ */
+ fun createInvalidAppMetadataWithInvalidTopLevelVersion(): PersistableBundle {
+ val validAppMetaData = createDefaultAppMetadata()
+ val validSafetyLabel = validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INVALID_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, validSafetyLabel)
+ }
+ }
+
+ /**
+ * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to no safety
+ * label version number.
+ */
+ fun createInvalidAppMetadataWithoutSafetyLabelVersion(): PersistableBundle {
+ val validAppMetaData = createDefaultAppMetadata()
+ val invalidSafetyLabel =
+ validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS).apply {
+ this?.remove(KEY_VERSION)
+ }
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, invalidSafetyLabel)
+ }
+ }
+
+ /**
+ * Returns invalid App Metadata [PersistableBundle] representation. Invalidity due to invalid
+ * safety label version number.
+ */
+ fun createInvalidAppMetadataWithInvalidSafetyLabelVersion(): PersistableBundle {
+ val validAppMetaData = createDefaultAppMetadata()
+ val invalidSafetyLabel =
+ validAppMetaData.getPersistableBundle(KEY_SAFETY_LABELS)?.apply {
+ putLong(KEY_VERSION, INVALID_SAFETY_LABELS_VERSION)
+ }
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, invalidSafetyLabel)
+ }
+ }
+ /** Returns an App Metadata [PersistableBundle] representation where no data is shared. */
+ fun createAppMetadataWithNoSharing(): PersistableBundle {
+ return createMetadataWithDataShared(PersistableBundle())
+ }
+
+ /**
+ * Returns an App Metadata [PersistableBundle] representation where location data is shared, but
+ * not for advertising purpose.
+ */
+ fun createAppMetadataWithLocationSharingNoAds(): PersistableBundle {
+ val locationBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(
+ APPROX_LOCATION,
+ PersistableBundle().apply {
+ putIntArray(
+ KEY_PURPOSES, listOf(PURPOSE_FRAUD_PREVENTION_SECURITY).toIntArray())
+ })
+ }
+
+ val dataSharedBundle =
+ PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
+
+ return createMetadataWithDataShared(dataSharedBundle)
+ }
+
+ /**
+ * Returns an App Metadata [PersistableBundle] representation where location data is shared,
+ * including for advertising purpose.
+ */
+ fun createAppMetadataWithLocationSharingAds(): PersistableBundle {
+ val locationBundle =
+ PersistableBundle().apply {
+ putPersistableBundle(
+ APPROX_LOCATION,
+ PersistableBundle().apply {
+ putIntArray(KEY_PURPOSES, listOf(PURPOSE_ADVERTISING).toIntArray())
+ })
+ }
+
+ val dataSharedBundle =
+ PersistableBundle().apply { putPersistableBundle(LOCATION_CATEGORY, locationBundle) }
+
+ return createMetadataWithDataShared(dataSharedBundle)
+ }
+
+ private fun createMetadataWithDataShared(
+ dataSharedBundle: PersistableBundle
+ ): PersistableBundle {
+ val dataLabelBundle =
+ PersistableBundle().apply { putPersistableBundle(KEY_DATA_SHARED, dataSharedBundle) }
+
+ val safetyLabelBundle =
+ PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_SAFETY_LABELS_VERSION)
+ putPersistableBundle(KEY_DATA_LABELS, dataLabelBundle)
+ }
+
+ return PersistableBundle().apply {
+ putLong(KEY_VERSION, INITIAL_TOP_LEVEL_VERSION)
+ putPersistableBundle(KEY_SAFETY_LABELS, safetyLabelBundle)
+ }
+ }
+
+ private const val INITIAL_SAFETY_LABELS_VERSION = 1L
+ private const val INITIAL_TOP_LEVEL_VERSION = 1L
+ private const val INVALID_SAFETY_LABELS_VERSION = -1L
+ private const val INVALID_TOP_LEVEL_VERSION = 0L
+
+ private const val LOCATION_CATEGORY = "location"
+ private const val APPROX_LOCATION = "approx_location"
+ private const val PURPOSE_FRAUD_PREVENTION_SECURITY = 4
+ private const val PURPOSE_ADVERTISING = 5
+
+ private const val KEY_VERSION = "version"
+ private const val KEY_SAFETY_LABELS = "safety_labels"
+ private const val KEY_INVALID = "invalid_safety_labels"
+ private const val KEY_DATA_SHARED = "data_shared"
+ private const val KEY_DATA_LABELS = "data_labels"
+ private const val KEY_PURPOSES = "purposes"
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt
new file mode 100644
index 000000000..5f2ae4670
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppPermissionTest.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.os.Build
+import android.provider.DeviceConfig
+import android.provider.Settings
+import android.provider.Settings.Secure.USER_SETUP_COMPLETE
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.modules.utils.build.SdkLevel
+import com.google.common.truth.Truth
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+/** App Permission page UI tests. */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class AppPermissionTest : BaseUsePermissionTest() {
+
+ @get:Rule
+ val deviceConfigPermissionRationaleEnabled =
+ DeviceConfigStateChangerRule(
+ context, DeviceConfig.NAMESPACE_PRIVACY, PERMISSION_RATIONALE_ENABLED, true.toString())
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue("Permission rationale is only available on U+", SdkLevel.isAtLeastU())
+ Assume.assumeFalse(isAutomotive)
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+
+ val userSetupComplete =
+ Settings.Secure.getInt(context.contentResolver, USER_SETUP_COMPLETE, 0) == 1
+
+ Truth.assertWithMessage("User setup must be complete before running this test")
+ .that(userSetupComplete)
+ .isTrue()
+ }
+
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndMetadata_packageSourceUnspecified() {
+ // Unspecified is the default, so no need to explicitly set it
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(true)
+
+ clickPermissionRationaleContentInAppPermission()
+ assertPermissionRationaleDialogIsVisible(expected = true, showSettingsSection = false)
+ }
+
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndMetadata_packageSourceStore() {
+ installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(true)
+
+ clickPermissionRationaleContentInAppPermission()
+ assertPermissionRationaleDialogIsVisible(expected = true, showSettingsSection = false)
+ }
+
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndMetadata_packageSourceLocalFile() {
+ installPackageWithInstallSourceAndMetadataFromLocalFile(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndMetadata_packageSourceDownloadedFile() {
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun showPermissionRationaleContainer_withInstallSourceAndMetadata_packageSourceOther() {
+ installPackageWithInstallSourceAndMetadataFromOther(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndNoMetadata() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndNullMetadata() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndEmptyMetadata() {
+ installPackageWithInstallSourceAndEmptyMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndInvalidMetadata() {
+ installPackageWithInstallSourceAndInvalidMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndMetadataWithoutTopLevelVersion() {
+ installPackageWithInstallSourceAndMetadataWithoutTopLevelVersion(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndMetadataWithInvalidTopLevelVersion() {
+ installPackageWithInstallSourceAndMetadataWithInvalidTopLevelVersion(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndMetadataWithoutSafetyLabelVersion() {
+ installPackageWithInstallSourceAndMetadataWithoutSafetyLabelVersion(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withInstallSourceAndMetadataWithInvalidSafetyLabelVersion()
+ {
+ installPackageWithInstallSourceAndMetadataWithInvalidSafetyLabelVersion(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withOutInstallSource() {
+ installPackageWithoutInstallSource(APP_APK_PATH_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ @Test
+ fun noShowPermissionRationaleContainer_withoutMetadata() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+
+ navigateToIndividualPermissionSetting(ACCESS_COARSE_LOCATION)
+
+ assertAppPermissionRationaleContainerIsVisible(false)
+ }
+
+ private fun assertAppPermissionRationaleContainerIsVisible(expected: Boolean) {
+ findView(By.res(APP_PERMISSION_RATIONALE_CONTAINER_VIEW), expected)
+ }
+
+ companion object {
+ private const val PERMISSION_RATIONALE_ENABLED = "permission_rationale_enabled"
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/AppStreamingPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/AppStreamingPermissionTest.kt
new file mode 100644
index 000000000..ba051952f
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/AppStreamingPermissionTest.kt
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.Manifest
+import android.app.Instrumentation
+import android.companion.virtual.VirtualDeviceManager
+import android.companion.virtual.VirtualDeviceManager.VirtualDevice
+import android.companion.virtual.VirtualDeviceParams
+import android.content.ComponentName
+import android.content.Intent
+import android.graphics.PixelFormat
+import android.hardware.display.DisplayManager
+import android.hardware.display.VirtualDisplayConfig
+import android.media.ImageReader
+import android.os.Build
+import android.provider.Settings
+import android.view.Display.DEFAULT_DISPLAY
+import android.virtualdevice.cts.common.FakeAssociationRule
+import android.virtualdevice.cts.common.util.VirtualDeviceTestUtils
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.UiObject2
+import com.android.compatibility.common.util.AdoptShellPermissionsRule
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assume.assumeNotNull
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** App Permission page UI tests. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
+class AppStreamingPermissionTest : BaseUsePermissionTest() {
+ companion object {
+ private const val DISPLAY_HEIGHT = 1920
+ private const val DISPLAY_WIDTH = 1080
+ }
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val defaultDeviceContext = instrumentation.targetContext
+ private val imageReader =
+ ImageReader.newInstance(
+ /* width= */ DISPLAY_WIDTH,
+ /* height= */ DISPLAY_HEIGHT,
+ PixelFormat.RGBA_8888,
+ /* maxImages= */ 1
+ )
+
+ private lateinit var virtualDeviceManager: VirtualDeviceManager
+ private lateinit var virtualDevice: VirtualDevice
+ private var virtualDisplayId: Int = -1
+
+ @get:Rule var mFakeAssociationRule = FakeAssociationRule()
+
+ @get:Rule
+ val mAdoptShellPermissionsRule =
+ AdoptShellPermissionsRule(
+ instrumentation.uiAutomation,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE
+ )
+
+ @Before
+ fun setup() {
+ callWithShellPermissionIdentity {
+ val virtualDeviceManager =
+ defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)
+ assumeNotNull(virtualDeviceManager)
+ this.virtualDeviceManager = virtualDeviceManager!!
+ virtualDevice =
+ virtualDeviceManager.createVirtualDevice(
+ mFakeAssociationRule.associationInfo.id,
+ VirtualDeviceParams.Builder().build()
+ )
+ val display =
+ virtualDevice.createVirtualDisplay(
+ VirtualDisplayConfig.Builder("testDisplay", DISPLAY_WIDTH, DISPLAY_HEIGHT, 240)
+ .setSurface(imageReader.surface)
+ .setFlags(
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC or
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED or
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+ )
+ .build(),
+ Runnable::run,
+ null
+ )
+ assertThat(display).isNotNull()
+ virtualDisplayId = display!!.display.displayId
+ }
+ }
+
+ @After
+ fun cleanup() {
+ callWithShellPermissionIdentity { virtualDevice.close() }
+ imageReader.close()
+ }
+
+ // TODO(b/291737919) Re-enable test once the flag is rolled out.
+ // TODO(b/301272559) Make test dependent on flag value once fixed.
+ @Test
+ @Ignore("b/291737919")
+ fun requestPermission_onVirtualDevice_showsAffectedDevice() {
+ installPackage(APP_APK_PATH_STREAMING)
+ requestPermissionOnDevice(virtualDisplayId)
+
+ assertPermissionMessageContainsDeviceName(virtualDisplayId, getHostDeviceName())
+ }
+
+ @Test
+ fun requestPermission_onHostDevice_doesNotShowAffectedDevice() {
+ installPackage(APP_APK_PATH_STREAMING)
+
+ requestPermissionOnDevice(DEFAULT_DISPLAY)
+
+ assertPermissionMessageDoesNotContainDeviceName(DEFAULT_DISPLAY, getHostDeviceName())
+ }
+
+ private fun getHostDeviceName(): String {
+ return Settings.Global.getString(context.contentResolver, Settings.Global.DEVICE_NAME)
+ }
+
+ private fun requestPermissionOnDevice(displayId: Int) {
+ val options = VirtualDeviceTestUtils.createActivityOptions(displayId)
+
+ val intent =
+ Intent()
+ .setComponent(
+ ComponentName(
+ "android.permissionui.cts.usepermission",
+ "android.permissionui.cts.usepermission.RequestPermissionActivity"
+ )
+ )
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ defaultDeviceContext.startActivity(intent, options)
+ }
+
+ private fun assertPermissionMessageContainsDeviceName(displayId: Int, deviceName: String) {
+ waitFindObject(By.displayId(displayId).res(getPermissionMessageResource()))
+ val text = findTextForView(By.displayId(displayId).res(getPermissionMessageResource()))
+ assertThat(text).contains(deviceName)
+ }
+
+ private fun assertPermissionMessageDoesNotContainDeviceName(
+ displayId: Int,
+ deviceName: String
+ ) {
+ waitFindObject(By.displayId(displayId).res(getPermissionMessageResource()))
+ val text = findTextForView(By.displayId(displayId).res(getPermissionMessageResource()))
+ assertThat(text).doesNotContain(deviceName)
+ }
+
+ private fun getPermissionMessageResource(): String =
+ when {
+ isAutomotive -> PERMISSION_MESSAGE_ID_AUTOMOTIVE
+ else -> PERMISSION_MESSAGE_ID
+ }
+
+ private fun findTextForView(selector: BySelector): String {
+ val timeoutMs = 10000L
+
+ var exception: Exception? = null
+ var view: UiObject2? = null
+ try {
+ view = waitFindObject(selector, timeoutMs)
+ } catch (e: Exception) {
+ exception = e
+ }
+ assertThat(exception).isNull()
+ assertThat(view).isNotNull()
+ return view!!.text
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt
new file mode 100644
index 000000000..169f1be5d
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2016 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.permissionui.cts
+
+import android.app.Instrumentation
+import android.app.PendingIntent
+import android.app.PendingIntent.FLAG_MUTABLE
+import android.app.PendingIntent.FLAG_UPDATE_CURRENT
+import android.app.UiAutomation
+import android.content.BroadcastReceiver
+import android.content.ComponentName
+import android.content.Context
+import android.content.Context.RECEIVER_EXPORTED
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageInstaller
+import android.content.pm.PackageInstaller.EXTRA_STATUS
+import android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE
+import android.content.pm.PackageInstaller.STATUS_FAILURE_INVALID
+import android.content.pm.PackageInstaller.STATUS_SUCCESS
+import android.content.pm.PackageInstaller.SessionParams
+import android.content.pm.PackageManager
+import android.content.res.Resources
+import android.os.PersistableBundle
+import android.os.SystemClock
+import android.platform.test.rule.ScreenRecordRule
+import android.provider.DeviceConfig
+import android.provider.Settings
+import android.text.Html
+import android.util.Log
+import androidx.test.core.app.ActivityScenario
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.StaleObjectException
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.UiScrollable
+import androidx.test.uiautomator.UiSelector
+import androidx.test.uiautomator.Until
+import com.android.compatibility.common.util.DisableAnimationRule
+import com.android.compatibility.common.util.FreezeRotationRule
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.UiAutomatorUtils2
+import com.android.modules.utils.build.SdkLevel
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.LinkedBlockingQueue
+import java.util.concurrent.TimeUnit
+import java.util.regex.Pattern
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Before
+import org.junit.Rule
+
+@ScreenRecordRule.ScreenRecord
+abstract class BasePermissionTest {
+ companion object {
+ private const val TAG = "BasePermissionTest"
+
+ private const val INSTALL_ACTION_CALLBACK = "BasePermissionTest.install_callback"
+
+ private const val MAX_SWIPES = 5
+
+ const val APK_DIRECTORY = "/data/local/tmp/cts-permissionui"
+
+ const val QUICK_CHECK_TIMEOUT_MILLIS = 100L
+ const val IDLE_TIMEOUT_MILLIS: Long = 1000
+ const val UNEXPECTED_TIMEOUT_MILLIS = 1000
+ const val TIMEOUT_MILLIS: Long = 20000
+ const val PACKAGE_INSTALLER_TIMEOUT = 60000L
+ const val NEW_WINDOW_TIMEOUT_MILLIS: Long = 20_000
+
+ @JvmStatic
+ protected val instrumentation: Instrumentation =
+ InstrumentationRegistry.getInstrumentation()
+ @JvmStatic
+ protected val context: Context = instrumentation.context
+ @JvmStatic
+ protected val uiAutomation: UiAutomation = instrumentation.uiAutomation
+ @JvmStatic
+ protected val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
+ @JvmStatic
+ protected val packageManager: PackageManager = context.packageManager
+ private val packageInstaller = packageManager.packageInstaller
+ @JvmStatic
+ private val mPermissionControllerResources: Resources = context.createPackageContext(
+ context.packageManager.permissionControllerPackageName, 0).resources
+
+ @JvmStatic
+ protected val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ @JvmStatic
+ protected val isWatch = packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ @JvmStatic
+ protected val isAutomotive =
+ packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ }
+
+ @get:Rule
+ val screenRecordRule = ScreenRecordRule(false, false)
+
+ @get:Rule
+ val disableAnimationRule = DisableAnimationRule()
+
+ @get:Rule
+ val freezeRotationRule = FreezeRotationRule()
+
+ var activityScenario: ActivityScenario<StartForFutureActivity>? = null
+
+ data class SessionResult(val status: Int?)
+
+ /** If a status was received the value of the status, otherwise null */
+ private var installSessionResult = LinkedBlockingQueue<SessionResult>()
+
+ private val installSessionResultReceiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val status = intent.getIntExtra(EXTRA_STATUS, STATUS_FAILURE_INVALID)
+ val msg = intent.getStringExtra(EXTRA_STATUS_MESSAGE)
+ Log.d(TAG, "status: $status, msg: $msg")
+
+ installSessionResult.offer(SessionResult(status))
+ }
+ }
+
+ private var screenTimeoutBeforeTest: Long = 0L
+
+ @Before
+ fun setUp() {
+ runWithShellPermissionIdentity {
+ screenTimeoutBeforeTest = Settings.System.getLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
+ )
+ Settings.System.putLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
+ )
+ }
+
+ uiDevice.wakeUp()
+ runShellCommand(instrumentation, "wm dismiss-keyguard")
+
+ uiDevice.findObject(By.text("Close"))?.click()
+ }
+
+ @Before
+ fun registerInstallSessionResultReceiver() {
+ context.registerReceiver(
+ installSessionResultReceiver, IntentFilter(INSTALL_ACTION_CALLBACK), RECEIVER_EXPORTED)
+ }
+
+ @After
+ fun unregisterInstallSessionResultReceiver() {
+ try {
+ context.unregisterReceiver(installSessionResultReceiver)
+ } catch (ignored: IllegalArgumentException) {}
+ }
+
+ @After
+ fun tearDown() {
+ runWithShellPermissionIdentity {
+ Settings.System.putLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
+ screenTimeoutBeforeTest
+ )
+ }
+
+ try {
+ activityScenario?.close()
+ } catch (e: NullPointerException) {
+ // ignore
+ }
+
+ pressHome()
+ }
+
+ protected fun setDeviceConfigPrivacyProperty(
+ propertyName: String,
+ value: String,
+ ) {
+ runWithShellPermissionIdentity(instrumentation.uiAutomation) {
+ val valueWasSet =
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_PRIVACY,
+ /* name = */ propertyName,
+ /* value = */ value,
+ /* makeDefault = */ false)
+ check(valueWasSet) { "Could not set $propertyName to $value" }
+ }
+ }
+
+ protected fun getPermissionControllerString(res: String, vararg formatArgs: Any): Pattern {
+ val textWithHtml = mPermissionControllerResources.getString(
+ mPermissionControllerResources.getIdentifier(
+ res, "string", "com.android.permissioncontroller"), *formatArgs)
+ val textWithoutHtml = Html.fromHtml(textWithHtml, 0).toString()
+ return Pattern.compile(Pattern.quote(textWithoutHtml),
+ Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE)
+ }
+
+ protected fun getPermissionControllerResString(res: String): String? {
+ try {
+ return mPermissionControllerResources.getString(
+ mPermissionControllerResources.getIdentifier(
+ res, "string", "com.android.permissioncontroller"))
+ } catch (e: Resources.NotFoundException) {
+ return null
+ }
+ }
+
+ protected fun byAnyText(vararg texts: String?): BySelector {
+ var regex = ""
+ for (text in texts) {
+ if (text != null) {
+ regex = regex + Pattern.quote(text) + "|"
+ }
+ }
+ if (regex.endsWith("|")) {
+ regex = regex.dropLast(1)
+ }
+ return By.text(Pattern.compile(regex, Pattern.CASE_INSENSITIVE or Pattern.UNICODE_CASE))
+ }
+
+ protected open fun installPackage(
+ apkPath: String,
+ reinstall: Boolean = false,
+ grantRuntimePermissions: Boolean = false,
+ expectSuccess: Boolean = true,
+ installSource: String? = null
+ ) {
+ val output = runShellCommandOrThrow(
+ "pm install${if (SdkLevel.isAtLeastU()) " --bypass-low-target-sdk-block" else ""} " +
+ "${if (reinstall) " -r" else ""}${if (grantRuntimePermissions) " -g"
+ else ""}${if (installSource != null) " -i $installSource" else ""} $apkPath"
+ ).trim()
+ if (expectSuccess) {
+ assertEquals("Success", output)
+ } else {
+ assertNotEquals("Success", output)
+ }
+ }
+
+ protected fun installPackageViaSession(
+ apkName: String,
+ appMetadata: PersistableBundle? = null,
+ packageSource: Int? = null
+ ) {
+ val (sessionId, session) = createPackageInstallerSession(packageSource)
+ runWithShellPermissionIdentity {
+ writePackageInstallerSession(session, apkName)
+ if (appMetadata != null) {
+ setAppMetadata(session, appMetadata)
+ }
+ commitPackageInstallerSession(session)
+
+ // No need to click installer UI here due to running in shell permission identity and
+ // not needing user interaciton to complete install. Install should have succeeded.
+ val result = getInstallSessionResult()
+ assertThat(result.status).isEqualTo(STATUS_SUCCESS)
+ }
+ }
+
+ protected fun uninstallPackage(packageName: String, requireSuccess: Boolean = true) {
+ val output = runShellCommand("pm uninstall $packageName").trim()
+ if (requireSuccess) {
+ assertEquals("Success", output)
+ }
+ }
+
+ protected fun waitFindObject(selector: BySelector): UiObject2 {
+ return findObjectWithRetry({ t -> UiAutomatorUtils2.waitFindObject(selector, t) })!!
+ }
+
+ protected fun waitFindObject(selector: BySelector, timeoutMillis: Long): UiObject2 {
+ return findObjectWithRetry({ t -> UiAutomatorUtils2.waitFindObject(selector, t) },
+ timeoutMillis)!!
+ }
+
+ protected fun waitFindObjectOrNull(selector: BySelector): UiObject2? {
+ return findObjectWithRetry({ t -> UiAutomatorUtils2.waitFindObjectOrNull(selector, t) })
+ }
+
+ protected fun waitFindObjectOrNull(selector: BySelector, timeoutMillis: Long): UiObject2? {
+ return findObjectWithRetry({ t -> UiAutomatorUtils2.waitFindObjectOrNull(selector, t) },
+ timeoutMillis)
+ }
+
+ private fun findObjectWithRetry(
+ automatorMethod: (timeoutMillis: Long) -> UiObject2?,
+ timeoutMillis: Long = 20_000L
+ ): UiObject2? {
+ val startTime = SystemClock.elapsedRealtime()
+ return try {
+ automatorMethod(timeoutMillis)
+ } catch (e: StaleObjectException) {
+ val remainingTime = timeoutMillis - (SystemClock.elapsedRealtime() - startTime)
+ if (remainingTime <= 0) {
+ throw e
+ }
+ automatorMethod(remainingTime)
+ }
+ }
+
+ protected fun click(selector: BySelector, timeoutMillis: Long = 20_000) {
+ waitFindObject(selector, timeoutMillis).click()
+ }
+
+ protected fun clickAndWaitForWindowTransition(selector: BySelector, timeoutMillis: Long = 20_000) {
+ waitFindObject(selector, timeoutMillis)
+ .clickAndWait(Until.newWindow(), NEW_WINDOW_TIMEOUT_MILLIS)
+ }
+
+ protected fun findView(selector: BySelector, expected: Boolean) {
+ val timeoutMs = if (expected) {
+ 10000L
+ } else {
+ 1000L
+ }
+
+ val exception = try {
+ waitFindObject(selector, timeoutMs)
+ null
+ } catch (e: Exception) {
+ e
+ }
+ Assert.assertTrue("Expected to find view: $expected", (exception == null) == expected)
+ }
+
+ protected fun clickPermissionControllerUi(selector: BySelector, timeoutMillis: Long = 20_000) {
+ click(selector.pkg(context.packageManager.permissionControllerPackageName), timeoutMillis)
+ }
+
+ /**
+ * Clicks Permission Controller UI with a swipe based timeout instead of a time based one
+ *
+ * Use this if finding some Permission Controller UI isn't time bound.
+ *
+ * @param text The text to search for
+ * @param maxSearchSwipes See {@link UiScrollable#setMaxSearchSwipes}
+ */
+ protected fun clickPermissionControllerUi(text: String, maxSearchSwipes: Int = 5) {
+ scrollToText(text, maxSearchSwipes).click()
+ }
+
+ private fun scrollToText(text: String, maxSearchSwipes: Int = MAX_SWIPES): UiObject2 {
+ val scrollable = UiScrollable(UiSelector().scrollable(true)).apply {
+ this.maxSearchSwipes = maxSearchSwipes
+ }
+
+ scrollable.scrollTextIntoView(text)
+
+ val foundObject = uiDevice.findObject(
+ By.text(text).pkg(context.packageManager.permissionControllerPackageName))
+ Assert.assertNotNull("View not found after scrolling", foundObject)
+
+ return foundObject
+ }
+
+ protected fun pressBack() {
+ uiDevice.pressBack()
+ }
+
+ protected fun pressHome() {
+ uiDevice.pressHome()
+ }
+
+ protected fun pressDPadDown() {
+ uiDevice.pressDPadDown()
+ waitForIdle()
+ }
+
+ protected fun waitForIdle() = uiAutomation.waitForIdle(IDLE_TIMEOUT_MILLIS, TIMEOUT_MILLIS)
+
+ protected fun startActivityForFuture(
+ intent: Intent
+ ): CompletableFuture<Instrumentation.ActivityResult> =
+ CompletableFuture<Instrumentation.ActivityResult>().also {
+ activityScenario = ActivityScenario.launch(
+ StartForFutureActivity::class.java).onActivity { activity ->
+ activity.startActivityForFuture(intent, it)
+ }
+ }
+
+ open fun enableComponent(component: ComponentName) {
+ packageManager.setComponentEnabledSetting(
+ component,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP)
+ }
+
+ open fun disableComponent(component: ComponentName) {
+ packageManager.setComponentEnabledSetting(
+ component,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP)
+ }
+
+ private fun createPackageInstallerSession(
+ packageSource: Int? = null
+ ): Pair<Int, PackageInstaller.Session> {
+ // Create session
+ val sessionParam = SessionParams(SessionParams.MODE_FULL_INSTALL)
+ if (packageSource != null) {
+ sessionParam.setPackageSource(packageSource)
+ }
+
+ val sessionId = packageInstaller.createSession(sessionParam)
+ val session = packageInstaller.openSession(sessionId)!!
+
+ return Pair(sessionId, session)
+ }
+
+ private fun writePackageInstallerSession(session: PackageInstaller.Session, apkName: String) {
+ val apkFile = File(APK_DIRECTORY, apkName)
+ // Write data to session
+ apkFile.inputStream().use { fileOnDisk ->
+ session
+ .openWrite(/* name= */ apkName, /* offsetBytes= */ 0, /* lengthBytes= */ -1)
+ .use { sessionFile -> fileOnDisk.copyTo(sessionFile) }
+ }
+ }
+
+ private fun commitPackageInstallerSession(session: PackageInstaller.Session) {
+ // PendingIntent that triggers a INSTALL_ACTION_CALLBACK broadcast that gets received by
+ // installSessionResultReceiver when install actions occur with this session
+ val installActionPendingIntent =
+ PendingIntent.getBroadcast(
+ context,
+ 0,
+ Intent(INSTALL_ACTION_CALLBACK).setPackage(context.packageName),
+ FLAG_UPDATE_CURRENT or FLAG_MUTABLE)
+ session.commit(installActionPendingIntent.intentSender)
+ }
+
+ private fun setAppMetadata(session: PackageInstaller.Session, data: PersistableBundle) {
+ try {
+ session.setAppMetadata(data)
+ } catch (e: Exception) {
+ session.abandon()
+ throw e
+ }
+ }
+
+ /** Wait for session's install result and return it */
+ private fun getInstallSessionResult(timeout: Long = PACKAGE_INSTALLER_TIMEOUT): SessionResult {
+ return installSessionResult.poll(timeout, TimeUnit.MILLISECONDS)
+ ?: SessionResult(null /* status */)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
new file mode 100644
index 000000000..289721b7c
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (C) 2016 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.permissionui.cts
+
+import android.Manifest
+import android.app.Activity
+import android.app.ActivityManager
+import android.app.Instrumentation
+import android.content.ComponentName
+import android.content.Intent
+import android.content.Intent.ACTION_REVIEW_APP_DATA_SHARING_UPDATES
+import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_OTHER
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_STORE
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Build
+import android.os.Process
+import android.provider.DeviceConfig
+import android.provider.Settings
+import android.text.Spanned
+import android.text.style.ClickableSpan
+import android.view.View
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.StaleObjectException
+import androidx.test.uiautomator.UiObjectNotFoundException
+import androidx.test.uiautomator.UiScrollable
+import androidx.test.uiautomator.UiSelector
+import androidx.test.uiautomator.Until
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.modules.utils.build.SdkLevel
+import java.util.concurrent.TimeUnit
+import java.util.regex.Pattern
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import java.util.concurrent.CompletableFuture
+
+abstract class BaseUsePermissionTest : BasePermissionTest() {
+ companion object {
+ const val APP_APK_NAME_31 = "CtsUsePermissionApp31.apk"
+
+ const val APP_APK_PATH_22 = "$APK_DIRECTORY/CtsUsePermissionApp22.apk"
+ const val APP_APK_PATH_22_CALENDAR_ONLY =
+ "$APK_DIRECTORY/CtsUsePermissionApp22CalendarOnly.apk"
+ const val APP_APK_PATH_22_NONE = "$APK_DIRECTORY/CtsUsePermissionApp22None.apk"
+ const val APP_APK_PATH_23 = "$APK_DIRECTORY/CtsUsePermissionApp23.apk"
+ const val APP_APK_PATH_25 = "$APK_DIRECTORY/CtsUsePermissionApp25.apk"
+ const val APP_APK_PATH_26 = "$APK_DIRECTORY/CtsUsePermissionApp26.apk"
+ const val APP_APK_PATH_28 = "$APK_DIRECTORY/CtsUsePermissionApp28.apk"
+ const val APP_APK_PATH_29 = "$APK_DIRECTORY/CtsUsePermissionApp29.apk"
+ const val APP_APK_PATH_30 = "$APK_DIRECTORY/CtsUsePermissionApp30.apk"
+ const val APP_APK_PATH_31 = "$APK_DIRECTORY/$APP_APK_NAME_31"
+ const val APP_APK_PATH_32 = "$APK_DIRECTORY/CtsUsePermissionApp32.apk"
+ const val APP_APK_PATH_STREAMING = "$APK_DIRECTORY/CtsUsePermissionAppStreaming.apk"
+
+ const val APP_APK_PATH_30_WITH_BACKGROUND =
+ "$APK_DIRECTORY/CtsUsePermissionApp30WithBackground.apk"
+ const val APP_APK_PATH_30_WITH_BLUETOOTH =
+ "$APK_DIRECTORY/CtsUsePermissionApp30WithBluetooth.apk"
+ const val APP_APK_PATH_LATEST = "$APK_DIRECTORY/CtsUsePermissionAppLatest.apk"
+ const val APP_APK_PATH_LATEST_NONE = "$APK_DIRECTORY/CtsUsePermissionAppLatestNone.apk"
+ const val APP_APK_PATH_WITH_OVERLAY = "$APK_DIRECTORY/CtsUsePermissionAppWithOverlay.apk"
+ const val APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31 =
+ "$APK_DIRECTORY/CtsCreateNotificationChannelsApp31.apk"
+ const val APP_APK_PATH_MEDIA_PERMISSION_33_WITH_STORAGE =
+ "$APK_DIRECTORY/CtsMediaPermissionApp33WithStorage.apk"
+ const val APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE =
+ "$APK_DIRECTORY/CtsUsePermissionAppImplicitUserSelectStorage.apk"
+ const val APP_APK_PATH_STORAGE_33 =
+ "$APK_DIRECTORY/CtsUsePermissionAppStorage33.apk"
+ const val APP_APK_PATH_OTHER_APP =
+ "$APK_DIRECTORY/CtsDifferentPkgNameApp.apk"
+ const val APP_PACKAGE_NAME = "android.permissionui.cts.usepermission"
+ const val OTHER_APP_PACKAGE_NAME = "android.permissionui.cts.usepermissionother"
+ const val TEST_INSTALLER_PACKAGE_NAME = "android.permissionui.cts"
+
+ const val ALLOW_ALL_BUTTON =
+ "com.android.permissioncontroller:id/permission_allow_all_button"
+ const val SELECT_BUTTON =
+ "com.android.permissioncontroller:id/permission_allow_selected_button"
+ const val DONT_SELECT_MORE_BUTTON =
+ "com.android.permissioncontroller:id/permission_dont_allow_more_selected_button"
+ const val ALLOW_BUTTON =
+ "com.android.permissioncontroller:id/permission_allow_button"
+ const val ALLOW_FOREGROUND_BUTTON =
+ "com.android.permissioncontroller:id/permission_allow_foreground_only_button"
+ const val DENY_BUTTON = "com.android.permissioncontroller:id/permission_deny_button"
+ const val DENY_AND_DONT_ASK_AGAIN_BUTTON =
+ "com.android.permissioncontroller:id/permission_deny_and_dont_ask_again_button"
+ const val NO_UPGRADE_BUTTON =
+ "com.android.permissioncontroller:id/permission_no_upgrade_button"
+ const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON =
+ "com.android.permissioncontroller:" +
+ "id/permission_no_upgrade_and_dont_ask_again_button"
+
+ const val ALLOW_ALWAYS_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/allow_always_radio_button"
+ const val ALLOW_RADIO_BUTTON = "com.android.permissioncontroller:id/allow_radio_button"
+ const val ALLOW_FOREGROUND_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/allow_foreground_only_radio_button"
+ const val ASK_RADIO_BUTTON = "com.android.permissioncontroller:id/ask_radio_button"
+ const val DENY_RADIO_BUTTON = "com.android.permissioncontroller:id/deny_radio_button"
+ const val SELECT_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/select_radio_button"
+
+ const val NOTIF_TEXT = "permgrouprequest_notifications"
+ const val ALLOW_BUTTON_TEXT = "grant_dialog_button_allow"
+ const val ALLOW_ALL_FILES_BUTTON_TEXT = "app_permission_button_allow_all_files"
+ const val ALLOW_FOREGROUND_BUTTON_TEXT = "grant_dialog_button_allow_foreground"
+ const val ALLOW_FOREGROUND_PREFERENCE_TEXT = "permission_access_only_foreground"
+ const val ASK_BUTTON_TEXT = "app_permission_button_ask"
+ const val ALLOW_ONE_TIME_BUTTON_TEXT = "grant_dialog_button_allow_one_time"
+ const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
+ const val DENY_ANYWAY_BUTTON_TEXT = "grant_dialog_button_deny_anyway"
+ const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
+ "grant_dialog_button_deny_and_dont_ask_again"
+ const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT = "grant_dialog_button_no_upgrade"
+ const val ALERT_DIALOG_MESSAGE = "android:id/message"
+ const val ALERT_DIALOG_OK_BUTTON = "android:id/button1"
+ const val APP_PERMISSION_RATIONALE_CONTAINER_VIEW =
+ "com.android.permissioncontroller:id/app_permission_rationale_container"
+ const val APP_PERMISSION_RATIONALE_CONTENT_VIEW =
+ "com.android.permissioncontroller:id/app_permission_rationale_content"
+ const val GRANT_DIALOG_PERMISSION_RATIONALE_CONTAINER_VIEW =
+ "com.android.permissioncontroller:id/permission_rationale_container"
+ const val PERMISSION_RATIONALE_ACTIVITY_TITLE_VIEW =
+ "com.android.permissioncontroller:id/permission_rationale_title"
+ const val DATA_SHARING_SOURCE_TITLE_ID =
+ "com.android.permissioncontroller:id/data_sharing_source_title"
+ const val DATA_SHARING_SOURCE_MESSAGE_ID =
+ "com.android.permissioncontroller:id/data_sharing_source_message"
+ const val PURPOSE_TITLE_ID = "com.android.permissioncontroller:id/purpose_title"
+ const val PURPOSE_MESSAGE_ID = "com.android.permissioncontroller:id/purpose_message"
+ const val LEARN_MORE_TITLE_ID = "com.android.permissioncontroller:id/learn_more_title"
+ const val LEARN_MORE_MESSAGE_ID = "com.android.permissioncontroller:id/learn_more_message"
+ const val PERMISSION_RATIONALE_SETTINGS_SECTION =
+ "com.android.permissioncontroller:id/settings_section"
+ const val SETTINGS_TITLE_ID =
+ "com.android.permissioncontroller:id/settings_title"
+ const val SETTINGS_MESSAGE_ID =
+ "com.android.permissioncontroller:id/settings_message"
+ const val PERMISSION_MESSAGE_ID = "com.android.permissioncontroller:id/permission_message"
+ const val PERMISSION_MESSAGE_ID_AUTOMOTIVE =
+ "com.android.permissioncontroller:id/car_ui_alert_title"
+
+ const val REQUEST_LOCATION_MESSAGE = "permgrouprequest_location"
+
+ const val DATA_SHARING_UPDATES = "Data sharing updates for location"
+ const val DATA_SHARING_UPDATES_SUBTITLE =
+ "These apps have changed the way they may share your location data. They may not" +
+ " have shared it before, or may now share it for advertising or marketing" +
+ " purposes."
+ const val DATA_SHARING_NO_UPDATES_MESSAGE = "No updates at this time"
+ const val UPDATES_IN_LAST_30_DAYS = "Updated within 30 days"
+ const val DATA_SHARING_UPDATES_FOOTER_MESSAGE =
+ "The developers of these apps provided info about their data sharing practices" +
+ " to an app store. They may update it over time.\n\nData sharing" +
+ " practices may vary based on your app version, use, region, and age."
+ const val LEARN_ABOUT_DATA_SHARING = "Learn about data sharing"
+ const val LOCATION_PERMISSION = "Location permission"
+ const val APP_PACKAGE_NAME_SUBSTRING = "android.permissionui"
+ const val NOW_SHARED_WITH_THIRD_PARTIES = "Your location data is now shared with third " +
+ "parties"
+ const val NOW_SHARED_WITH_THIRD_PARTIES_FOR_ADS = "Your location data is now shared with " +
+ "third parties for advertising or marketing"
+ const val PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS =
+ "data_sharing_update_period_millis"
+ const val PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP =
+ "max_safety_labels_persisted_per_app"
+
+ // The highest SDK for which the system will show a "low SDK" warning when launching the app
+ const val MAX_SDK_FOR_SDK_WARNING = 27
+ const val MIN_SDK_FOR_RUNTIME_PERMS = 23
+
+ val TEST_INSTALLER_ACTIVITY_COMPONENT_NAME =
+ ComponentName(context, TestInstallerActivity::class.java)
+
+ val MEDIA_PERMISSIONS: Set<String> = mutableSetOf(
+ Manifest.permission.ACCESS_MEDIA_LOCATION,
+ Manifest.permission.READ_MEDIA_AUDIO,
+ Manifest.permission.READ_MEDIA_IMAGES,
+ Manifest.permission.READ_MEDIA_VIDEO,
+ ).apply {
+ if (SdkLevel.isAtLeastU()) {
+ add(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
+ }
+ }.toSet()
+
+ val STORAGE_AND_MEDIA_PERMISSIONS = MEDIA_PERMISSIONS
+ .plus(Manifest.permission.READ_EXTERNAL_STORAGE)
+ .plus(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+
+ @JvmStatic
+ protected val PICKER_ENABLED_SETTING = "photo_picker_prompt_enabled"
+
+ @JvmStatic
+ protected fun isPhotoPickerPermissionPromptEnabled(): Boolean {
+ return SdkLevel.isAtLeastU() &&
+ !isTv && !isAutomotive && !isWatch &&
+ callWithShellPermissionIdentity {
+ DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_PRIVACY, PICKER_ENABLED_SETTING, true)
+ }
+ }
+ }
+
+ enum class PermissionState {
+ ALLOWED,
+ DENIED,
+ DENIED_WITH_PREJUDICE
+ }
+
+ private val platformResources = context.createPackageContext("android", 0).resources
+ private val permissionToLabelResNameMap = mapOf(
+ // Contacts
+ android.Manifest.permission.READ_CONTACTS
+ to "@android:string/permgrouplab_contacts",
+ android.Manifest.permission.WRITE_CONTACTS
+ to "@android:string/permgrouplab_contacts",
+ // Calendar
+ android.Manifest.permission.READ_CALENDAR
+ to "@android:string/permgrouplab_calendar",
+ android.Manifest.permission.WRITE_CALENDAR
+ to "@android:string/permgrouplab_calendar",
+ // SMS
+ android.Manifest.permission.SEND_SMS to "@android:string/permgrouplab_sms",
+ android.Manifest.permission.RECEIVE_SMS to "@android:string/permgrouplab_sms",
+ android.Manifest.permission.READ_SMS to "@android:string/permgrouplab_sms",
+ android.Manifest.permission.RECEIVE_WAP_PUSH to "@android:string/permgrouplab_sms",
+ android.Manifest.permission.RECEIVE_MMS to "@android:string/permgrouplab_sms",
+ "android.permission.READ_CELL_BROADCASTS" to "@android:string/permgrouplab_sms",
+ // Storage
+ android.Manifest.permission.READ_EXTERNAL_STORAGE
+ to "@android:string/permgrouplab_storage",
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+ to "@android:string/permgrouplab_storage",
+ // Location
+ android.Manifest.permission.ACCESS_FINE_LOCATION
+ to "@android:string/permgrouplab_location",
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ to "@android:string/permgrouplab_location",
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+ to "@android:string/permgrouplab_location",
+ // Phone
+ android.Manifest.permission.READ_PHONE_STATE
+ to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.CALL_PHONE to "@android:string/permgrouplab_phone",
+ "android.permission.ACCESS_IMS_CALL_SERVICE"
+ to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.READ_CALL_LOG to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.WRITE_CALL_LOG to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.ADD_VOICEMAIL to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.USE_SIP to "@android:string/permgrouplab_phone",
+ android.Manifest.permission.PROCESS_OUTGOING_CALLS
+ to "@android:string/permgrouplab_phone",
+ // Microphone
+ android.Manifest.permission.RECORD_AUDIO
+ to "@android:string/permgrouplab_microphone",
+ // Camera
+ android.Manifest.permission.CAMERA to "@android:string/permgrouplab_camera",
+ // Body sensors
+ android.Manifest.permission.BODY_SENSORS to "@android:string/permgrouplab_sensors",
+ android.Manifest.permission.BODY_SENSORS_BACKGROUND
+ to "@android:string/permgrouplab_sensors",
+ // Bluetooth
+ android.Manifest.permission.BLUETOOTH_CONNECT to
+ "@android:string/permgrouplab_nearby_devices",
+ android.Manifest.permission.BLUETOOTH_SCAN to
+ "@android:string/permgrouplab_nearby_devices",
+ // Aural
+ android.Manifest.permission.READ_MEDIA_AUDIO to
+ "@android:string/permgrouplab_readMediaAural",
+ // Visual
+ android.Manifest.permission.READ_MEDIA_IMAGES to
+ "@android:string/permgrouplab_readMediaVisual",
+ android.Manifest.permission.READ_MEDIA_VIDEO to
+ "@android:string/permgrouplab_readMediaVisual"
+ )
+
+ @Before
+ @After
+ fun uninstallApp() {
+ uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
+ }
+
+ override fun installPackage(
+ apkPath: String,
+ reinstall: Boolean,
+ grantRuntimePermissions: Boolean,
+ expectSuccess: Boolean,
+ installSource: String?
+ ) {
+ installPackage(apkPath, reinstall, grantRuntimePermissions, expectSuccess, installSource,
+ false)
+ }
+
+ fun installPackage(
+ apkPath: String,
+ reinstall: Boolean = false,
+ grantRuntimePermissions: Boolean = false,
+ expectSuccess: Boolean = true,
+ installSource: String? = null,
+ skipClearLowSdkDialog: Boolean = false
+ ) {
+ super.installPackage(apkPath, reinstall, grantRuntimePermissions, expectSuccess,
+ installSource
+ )
+
+ val targetSdk = getTargetSdk()
+ // If the targetSDK is high enough, the low sdk warning won't show. If the SDK is
+ // below runtime permissions, the dialog will be delayed by the permission review screen.
+ // If success is not expected, don't bother trying
+ if (targetSdk > MAX_SDK_FOR_SDK_WARNING || targetSdk < MIN_SDK_FOR_RUNTIME_PERMS ||
+ !expectSuccess || skipClearLowSdkDialog) {
+ return
+ }
+
+ val finishOnCreateIntent = Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.FinishOnCreateActivity"
+ )
+ flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
+ }
+
+ // Check if an activity resolves for the test app. If it doesn't, then our test app doesn't
+ // have the usual set of activities, and likely won't be opened, and thus, won't show the
+ // dialog
+ callWithShellPermissionIdentity {
+ context.packageManager.resolveActivity(finishOnCreateIntent, PackageManager.MATCH_ALL)
+ } ?: return
+
+ // Start the test app, and expect the targetSDK warning dialog
+ context.startActivity(finishOnCreateIntent)
+ clearTargetSdkWarning()
+ // Kill the test app, so that the next time we launch, we don't see the app warning dialog
+ killTestApp()
+ }
+
+ protected fun clearTargetSdkWarning(timeoutMillis: Long = TIMEOUT_MILLIS) {
+ if (SdkLevel.isAtLeastV()) {
+ // In V and above, the target SDK dialog can be disabled via system property
+ return
+ }
+
+ waitFindObjectOrNull(By.res("android:id/button1"), timeoutMillis)?.let {
+ try {
+ it.click()
+ } catch (e: StaleObjectException) {
+ // Click sometimes fails with StaleObjectException (b/280430717).
+ e.printStackTrace()
+ }
+ }
+ }
+
+ protected fun killTestApp() {
+ pressBack()
+ pressBack()
+ runWithShellPermissionIdentity {
+ val am = context.getSystemService(ActivityManager::class.java)!!
+ am.forceStopPackage(APP_PACKAGE_NAME)
+ }
+ waitForIdle()
+ }
+
+ protected fun clickPermissionReviewContinue() {
+ if (isAutomotive || isWatch) {
+ clickAndWaitForWindowTransition(
+ By.text(getPermissionControllerString("review_button_continue")), TIMEOUT_MILLIS * 2
+ )
+ } else {
+ clickAndWaitForWindowTransition(
+ By.res("com.android.permissioncontroller:id/continue_button"))
+ }
+ }
+
+ protected fun clickPermissionReviewContinueAndClearSdkWarning() {
+ clickPermissionReviewContinue()
+ clearTargetSdkWarning()
+ }
+
+ protected fun installPackageWithInstallSourceAndEmptyMetadata(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createEmptyAppMetadata())
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadata(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createDefaultAppMetadata())
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataFromStore(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createDefaultAppMetadata(),
+ PACKAGE_SOURCE_STORE)
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataFromLocalFile(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createDefaultAppMetadata(),
+ PACKAGE_SOURCE_LOCAL_FILE)
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataFromDownloadedFile(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createDefaultAppMetadata(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE)
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataFromOther(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createDefaultAppMetadata(),
+ PACKAGE_SOURCE_OTHER)
+ }
+
+ protected fun installPackageWithInstallSourceAndNoMetadata(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName)
+ }
+
+ protected fun installPackageWithInstallSourceAndInvalidMetadata(
+ apkName: String
+ ) {
+ installPackageViaSession(apkName, AppMetadata.createInvalidAppMetadata())
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataWithoutTopLevelVersion(
+ apkName: String
+ ) {
+ installPackageViaSession(
+ apkName, AppMetadata.createInvalidAppMetadataWithoutTopLevelVersion()
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataWithInvalidTopLevelVersion(
+ apkName: String
+ ) {
+ installPackageViaSession(
+ apkName, AppMetadata.createInvalidAppMetadataWithInvalidTopLevelVersion()
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataWithoutSafetyLabelVersion(
+ apkName: String
+ ) {
+ installPackageViaSession(
+ apkName, AppMetadata.createInvalidAppMetadataWithoutSafetyLabelVersion()
+ )
+ }
+
+ protected fun installPackageWithInstallSourceAndMetadataWithInvalidSafetyLabelVersion(
+ apkName: String
+ ) {
+ installPackageViaSession(
+ apkName, AppMetadata.createInvalidAppMetadataWithInvalidSafetyLabelVersion()
+ )
+ }
+
+ protected fun installPackageWithoutInstallSource(
+ apkName: String
+ ) {
+ // TODO(b/257293222): Update/remove when hooking up PackageManager APIs
+ installPackage(apkName)
+ }
+
+ protected fun assertPermissionRationaleActivityTitleIsVisible(expected: Boolean) {
+ findView(By.res(PERMISSION_RATIONALE_ACTIVITY_TITLE_VIEW), expected = expected)
+ }
+
+ protected fun assertPermissionRationaleActivityDataSharingSourceSectionVisible(
+ expected: Boolean
+ ) {
+ findView(By.res(DATA_SHARING_SOURCE_TITLE_ID), expected = expected)
+ findView(By.res(DATA_SHARING_SOURCE_MESSAGE_ID), expected = expected)
+ }
+
+ protected fun assertPermissionRationaleActivityPurposeSectionVisible(expected: Boolean) {
+ findView(By.res(PURPOSE_TITLE_ID), expected = expected)
+ findView(By.res(PURPOSE_MESSAGE_ID), expected = expected)
+ }
+
+ protected fun assertPermissionRationaleActivityLearnMoreSectionVisible(expected: Boolean) {
+ findView(By.res(LEARN_MORE_TITLE_ID), expected = expected)
+ findView(By.res(LEARN_MORE_MESSAGE_ID), expected = expected)
+ }
+
+ protected fun assertPermissionRationaleActivitySettingsSectionVisible(expected: Boolean) {
+ findView(By.res(PERMISSION_RATIONALE_SETTINGS_SECTION), expected = expected)
+ findView(By.res(SETTINGS_TITLE_ID), expected = expected)
+ findView(By.res(SETTINGS_MESSAGE_ID), expected = expected)
+ }
+
+ protected fun assertPermissionRationaleDialogIsVisible(
+ expected: Boolean,
+ showSettingsSection: Boolean = true
+ ) {
+ assertPermissionRationaleActivityTitleIsVisible(expected)
+ assertPermissionRationaleActivityDataSharingSourceSectionVisible(expected)
+ assertPermissionRationaleActivityPurposeSectionVisible(expected)
+ assertPermissionRationaleActivityLearnMoreSectionVisible(expected)
+ if (expected) {
+ assertPermissionRationaleActivitySettingsSectionVisible(showSettingsSection)
+ }
+ }
+
+ protected fun assertPermissionRationaleContainerOnGrantDialogIsVisible(expected: Boolean) {
+ findView(By.res(GRANT_DIALOG_PERMISSION_RATIONALE_CONTAINER_VIEW), expected = expected)
+ }
+
+ protected fun clickPermissionReviewCancel() {
+ if (isAutomotive || isWatch) {
+ clickAndWaitForWindowTransition(
+ By.text(getPermissionControllerString("review_button_cancel")))
+ } else {
+ clickAndWaitForWindowTransition(
+ By.res("com.android.permissioncontroller:id/cancel_button"))
+ }
+ }
+
+ protected fun approvePermissionReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
+ clickPermissionReviewContinueAndClearSdkWarning()
+ }
+ }
+
+ protected fun cancelPermissionReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_CANCELED) {
+ clickPermissionReviewCancel()
+ }
+ }
+
+ protected fun assertAppDoesNotNeedPermissionReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {}
+ }
+
+ protected inline fun startAppActivityAndAssertResultCode(
+ expectedResultCode: Int,
+ block: () -> Unit
+ ) {
+ val future = startActivityForFuture(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.FinishOnCreateActivity"
+ )
+ }
+ )
+ block()
+ assertEquals(
+ expectedResultCode, future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS).resultCode
+ )
+ }
+
+ protected inline fun requestAppPermissionsForNoResult(
+ vararg permissions: String?,
+ crossinline block: () -> Unit
+ ) {
+ // Request the permissions
+ doAndWaitForWindowTransition {
+ context.startActivity(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.RequestPermissionsActivity"
+ )
+ putExtra("$APP_PACKAGE_NAME.PERMISSIONS", permissions)
+ addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK)
+ }
+ )
+ }
+ // Perform the post-request action
+ block()
+ }
+
+ protected inline fun requestAppPermissions(
+ vararg permissions: String?,
+ askTwice: Boolean = false,
+ waitForWindowTransition: Boolean = true,
+ crossinline block: () -> Unit
+ ): Instrumentation.ActivityResult {
+ // Request the permissions
+ lateinit var future: CompletableFuture<Instrumentation.ActivityResult>
+ doAndWaitForWindowTransition {
+ future = startActivityForFuture(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.RequestPermissionsActivity"
+ )
+ putExtra("$APP_PACKAGE_NAME.PERMISSIONS", permissions)
+ putExtra("$APP_PACKAGE_NAME.ASK_TWICE", askTwice)
+ }
+ )
+ }
+
+ // Notification permission prompt is shown first, so get it out of the way
+ clickNotificationPermissionRequestAllowButtonIfAvailable()
+ // Perform the post-request action
+ if (waitForWindowTransition) {
+ doAndWaitForWindowTransition {
+ block()
+ }
+ } else {
+ block()
+ }
+ return future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ }
+
+ protected inline fun requestAppPermissionsAndAssertResult(
+ permissions: Array<out String?>,
+ permissionAndExpectedGrantResults: Array<out Pair<String?, Boolean>>,
+ askTwice: Boolean = false,
+ waitForWindowTransition: Boolean = true,
+ crossinline block: () -> Unit
+ ) {
+ val result = requestAppPermissions(
+ *permissions,
+ askTwice = askTwice,
+ waitForWindowTransition = waitForWindowTransition,
+ block = block
+ )
+ assertEquals(
+ "Permission request result had unexpected resultCode:",
+ Activity.RESULT_OK,
+ result.resultCode
+ )
+
+ val responseSize: Int =
+ result.resultData!!.getStringArrayExtra("$APP_PACKAGE_NAME.PERMISSIONS")!!.size
+ assertEquals("Permission request result had unexpected number of grant results:",
+ responseSize,
+ result.resultData!!.getIntArrayExtra("$APP_PACKAGE_NAME.GRANT_RESULTS")!!.size
+ )
+
+ // Note that the behavior around requesting `null` permissions changed in the platform
+ // in Android U. Currently, null permissions are ignored and left out of the result set.
+ assertTrue("Permission request result had fewer permissions than request",
+ permissions.size >= responseSize)
+ assertEquals("Permission request result had unexpected grant results:",
+ permissionAndExpectedGrantResults
+ .filter { it.first != null }
+ .toList(),
+ result.resultData!!.getStringArrayExtra("$APP_PACKAGE_NAME.PERMISSIONS")!!
+ .filterNotNull()
+ .zip(
+ result.resultData!!.getIntArrayExtra("$APP_PACKAGE_NAME.GRANT_RESULTS")!!
+ .map { it == PackageManager.PERMISSION_GRANTED }
+ )
+ )
+
+ permissionAndExpectedGrantResults.forEach {
+ it.first?.let { permission ->
+ assertAppHasPermission(permission, it.second)
+ }
+ }
+ }
+
+ protected inline fun requestAppPermissionsAndAssertResult(
+ vararg permissionAndExpectedGrantResults: Pair<String?, Boolean>,
+ askTwice: Boolean = false,
+ waitForWindowTransition: Boolean = true,
+ crossinline block: () -> Unit
+ ) {
+ requestAppPermissionsAndAssertResult(
+ permissionAndExpectedGrantResults.map { it.first }.toTypedArray(),
+ permissionAndExpectedGrantResults,
+ askTwice,
+ waitForWindowTransition,
+ block
+ )
+ }
+
+ // Perform the requested action, then wait both for the action to complete, and for at least
+ // one window transition to occur since the moment the action begins executing.
+ protected inline fun doAndWaitForWindowTransition(
+ crossinline block: () -> Unit
+ ) {
+ val timeoutOccurred = !uiDevice.performActionAndWait({
+ block()
+ }, Until.newWindow(), NEW_WINDOW_TIMEOUT_MILLIS)
+
+ if (timeoutOccurred) {
+ throw RuntimeException("Timed out waiting for window transition.")
+ }
+ }
+
+ protected fun findPermissionRequestAllowButton(timeoutMillis: Long = 20000) {
+ if (isAutomotive || isWatch) {
+ waitFindObject(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)), timeoutMillis)
+ } else {
+ waitFindObject(By.res(ALLOW_BUTTON), timeoutMillis)
+ }
+ }
+
+ protected fun clickPermissionRequestAllowButton(timeoutMillis: Long = 20000) {
+ if (isAutomotive || isWatch) {
+ click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)), timeoutMillis)
+ } else {
+ click(By.res(ALLOW_BUTTON), timeoutMillis)
+ }
+ }
+
+ protected fun clickPermissionRequestAllowAllButton(timeoutMillis: Long = 20000) {
+ click(By.res(ALLOW_ALL_BUTTON), timeoutMillis)
+ }
+
+ /**
+ * Only for use in tests that are not testing the notification permission popup, on T devices
+ */
+ protected fun clickNotificationPermissionRequestAllowButtonIfAvailable() {
+ if (!SdkLevel.isAtLeastT()) {
+ return
+ }
+
+ if (waitFindObjectOrNull(By.text(getPermissionControllerString(
+ NOTIF_TEXT, APP_PACKAGE_NAME
+ )), 1000) != null) {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+ } else {
+ click(By.res(ALLOW_BUTTON))
+ }
+ }
+ }
+
+ protected fun clickPermissionRequestSettingsLinkAndAllowAlways() {
+ clickPermissionRequestSettingsLink()
+ eventually({
+ clickAllowAlwaysInSettings()
+ }, TIMEOUT_MILLIS * 2)
+ pressBack()
+ }
+
+ protected fun clickAllowAlwaysInSettings() {
+ if (isAutomotive || isTv || isWatch) {
+ click(By.text(getPermissionControllerString("app_permission_button_allow_always")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/allow_always_radio_button"))
+ }
+ }
+
+ protected fun clickAllowForegroundInSettings() {
+ click(By.res(ALLOW_FOREGROUND_RADIO_BUTTON))
+ }
+
+ protected fun clicksDenyInSettings() {
+ if (isAutomotive || isWatch) {
+ click(By.text(getPermissionControllerString("app_permission_button_deny")))
+ } else {
+ click(By.res("com.android.permissioncontroller:id/deny_radio_button"))
+ }
+ }
+
+ protected fun findPermissionRequestAllowForegroundButton(timeoutMillis: Long = 20000) {
+ if (isAutomotive || isWatch) {
+ waitFindObject(By.text(
+ getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT)), timeoutMillis)
+ } else {
+ waitFindObject(By.res(ALLOW_FOREGROUND_BUTTON), timeoutMillis)
+ }
+ }
+
+ protected fun clickPermissionRequestAllowForegroundButton(timeoutMillis: Long = 10_000) {
+ if (isAutomotive || isWatch) {
+ click(By.text(
+ getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT)), timeoutMillis)
+ } else {
+ click(By.res(ALLOW_FOREGROUND_BUTTON), timeoutMillis)
+ }
+ }
+
+ protected fun clickPermissionRequestDenyButton() {
+ if (isAutomotive || isWatch || isTv) {
+ click(By.text(getPermissionControllerString(DENY_BUTTON_TEXT)))
+ } else {
+ click(By.res(DENY_BUTTON))
+ }
+ }
+
+ protected fun clickPermissionRequestSettingsLinkAndDeny() {
+ clickPermissionRequestSettingsLink()
+ eventually({
+ clicksDenyInSettings()
+ }, TIMEOUT_MILLIS * 2)
+ pressBack()
+ }
+
+ protected fun clickPermissionRequestSettingsLink() {
+ eventually {
+ // UiObject2 doesn't expose CharSequence.
+ val node = if (isAutomotive) {
+ // Should match "Allow in settings." (location) and "go to settings." (body sensors)
+ uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByText(
+ " settings."
+ )[0]
+ } else {
+ uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ "com.android.permissioncontroller:id/detail_message"
+ )[0]
+ }
+ if (!node.isVisibleToUser) {
+ scrollToBottom()
+ }
+ assertTrue(node.isVisibleToUser)
+ val text = node.text as Spanned
+ val clickableSpan = text.getSpans(0, text.length, ClickableSpan::class.java)[0]
+ // We could pass in null here in Java, but we need an instance in Kotlin.
+ doAndWaitForWindowTransition {
+ clickableSpan.onClick(View(context))
+ }
+ }
+ }
+
+ protected fun clickPermissionRequestDenyAndDontAskAgainButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT)))
+ } else if (isWatch) {
+ click(By.text(getPermissionControllerString(DENY_BUTTON_TEXT)))
+ } else {
+ click(By.res(DENY_AND_DONT_ASK_AGAIN_BUTTON))
+ }
+ }
+
+ // Only used in TV and Watch form factors
+ protected fun clickPermissionRequestDontAskAgainButton() {
+ if (isWatch) {
+ click(By.text(getPermissionControllerString(DENY_BUTTON_TEXT)))
+ } else {
+ click(
+ By.res("com.android.permissioncontroller:id/permission_deny_dont_ask_again_button")
+ )
+ }
+ }
+
+ protected fun clickPermissionRequestNoUpgradeAndDontAskAgainButton() {
+ if (isAutomotive) {
+ click(By.text(getPermissionControllerString(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT)))
+ } else {
+ click(By.res(NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON))
+ }
+ }
+
+ protected fun clickPermissionRationaleContentInAppPermission() {
+ clickAndWaitForWindowTransition(By.res(APP_PERMISSION_RATIONALE_CONTENT_VIEW))
+ }
+
+ protected fun clickPermissionRationaleViewInGrantDialog() {
+ clickAndWaitForWindowTransition(By.res(GRANT_DIALOG_PERMISSION_RATIONALE_CONTAINER_VIEW))
+ }
+
+ protected fun grantAppPermissionsByUi(vararg permissions: String) {
+ setAppPermissionState(*permissions, state = PermissionState.ALLOWED, isLegacyApp = false)
+ }
+
+ protected fun grantRuntimePermissions(vararg permissions: String) {
+ for (permission in permissions) {
+ uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME, permission)
+ }
+ }
+
+ protected fun revokeAppPermissionsByUi(
+ vararg permissions: String,
+ isLegacyApp: Boolean = false
+ ) {
+ setAppPermissionState(*permissions, state = PermissionState.DENIED,
+ isLegacyApp = isLegacyApp)
+ }
+
+ private fun navigateToAppPermissionSettings() {
+ if (isTv) {
+ // Dismiss DeprecatedTargetSdkVersionDialog, if present
+ if (waitFindObjectOrNull(By.text(APP_PACKAGE_NAME), 1000L) != null) {
+ pressBack()
+ }
+ pressHome()
+ } else {
+ pressBack()
+ pressBack()
+ pressBack()
+ }
+
+ // Try multiple times as the AppInfo page might have read stale data
+ eventually({
+ try {
+ // Open the app details settings
+ doAndWaitForWindowTransition {
+ context.startActivity(
+ Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
+ data = Uri.fromParts("package", APP_PACKAGE_NAME, null)
+ addCategory(Intent.CATEGORY_DEFAULT)
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ }
+ )
+ }
+ if (isTv) {
+ pressDPadDown()
+ pressDPadDown()
+ pressDPadDown()
+ pressDPadDown()
+ }
+ // Open the permissions UI
+ clickAndWaitForWindowTransition(byTextRes(R.string.permissions).enabled(true))
+ } catch (e: Exception) {
+ pressBack()
+ throw e
+ }
+ }, TIMEOUT_MILLIS)
+ }
+
+ private fun getTargetSdk(packageName: String = APP_PACKAGE_NAME): Int {
+ return callWithShellPermissionIdentity {
+ try {
+ context.packageManager.getApplicationInfo(packageName, 0).targetSdkVersion
+ } catch (e: PackageManager.NameNotFoundException) {
+ -1
+ }
+ }
+ }
+
+ protected fun navigateToIndividualPermissionSetting(
+ permission: String,
+ manuallyNavigate: Boolean = false
+ ) {
+ val useLegacyNavigation = isWatch || isAutomotive || manuallyNavigate
+ if (useLegacyNavigation) {
+ navigateToAppPermissionSettings()
+ val permissionLabel = getPermissionLabel(permission)
+ if (isWatch) {
+ clickAndWaitForWindowTransition(By.text(permissionLabel), 40_000)
+ } else {
+ clickPermissionControllerUi(By.text(permissionLabel))
+ }
+ return
+ }
+ doAndWaitForWindowTransition {
+ runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSION).apply {
+ putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ putExtra(Intent.EXTRA_PERMISSION_NAME, permission)
+ putExtra(Intent.EXTRA_USER, Process.myUserHandle())
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ })
+ }
+ }
+ }
+
+ /** Starts activity with intent [ACTION_REVIEW_APP_DATA_SHARING_UPDATES]. */
+ fun startAppDataSharingUpdatesActivity() {
+ doAndWaitForWindowTransition {
+ runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(ACTION_REVIEW_APP_DATA_SHARING_UPDATES).apply {
+ addFlags(FLAG_ACTIVITY_NEW_TASK)
+ })
+ }
+ }
+ }
+
+ private fun setAppPermissionState(
+ vararg permissions: String,
+ state: PermissionState,
+ isLegacyApp: Boolean,
+ manuallyNavigate: Boolean = false,
+ ) {
+ val useLegacyNavigation = isWatch || isAutomotive || manuallyNavigate
+ if (useLegacyNavigation) {
+ navigateToAppPermissionSettings()
+ }
+
+ val navigatedGroupLabels = mutableSetOf<String>()
+ for (permission in permissions) {
+ // Find the permission screen
+ val permissionLabel = getPermissionLabel(permission)
+ if (navigatedGroupLabels.contains(getPermissionLabel(permission))) {
+ continue
+ }
+ navigatedGroupLabels.add(permissionLabel)
+ if (useLegacyNavigation) {
+ if (isWatch) {
+ click(By.text(permissionLabel), 40_000)
+ } else if (isAutomotive) {
+ clickPermissionControllerUi(permissionLabel)
+ } else {
+ clickPermissionControllerUi(By.text(permissionLabel))
+ }
+ } else {
+ doAndWaitForWindowTransition {
+ runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSION).apply {
+ putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ putExtra(Intent.EXTRA_PERMISSION_NAME, permission)
+ putExtra(Intent.EXTRA_USER, Process.myUserHandle())
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ })
+ }
+ }
+ }
+
+ val wasGranted = if (isAutomotive) {
+ // Automotive doesn't support one time permissions, and thus
+ // won't show an "Ask every time" message
+ !waitFindObject(By.text(
+ getPermissionControllerString("app_permission_button_deny"))).isChecked
+ } else if (isTv || isWatch) {
+ !(waitFindObject(
+ By.text(getPermissionControllerString(DENY_BUTTON_TEXT))).isChecked ||
+ (!isLegacyApp && hasAskButton(permission) && waitFindObject(
+ By.text(getPermissionControllerString(ASK_BUTTON_TEXT))).isChecked))
+ } else {
+ !(waitFindObject(By.res(DENY_RADIO_BUTTON)).isChecked ||
+ (!isLegacyApp && hasAskButton(permission) &&
+ waitFindObject(By.res(ASK_RADIO_BUTTON)).isChecked))
+ }
+ var alreadyChecked = false
+ val button = waitFindObject(
+ if (isAutomotive) {
+ // Automotive doesn't support one time permissions, and thus
+ // won't show an "Ask every time" message
+ when (state) {
+ PermissionState.ALLOWED ->
+ if (showsForegroundOnlyButton(permission)) {
+ By.text(getPermissionControllerString(
+ "app_permission_button_allow_foreground"))
+ } else {
+ By.text(getPermissionControllerString(
+ "app_permission_button_allow"))
+ }
+ PermissionState.DENIED -> By.text(
+ getPermissionControllerString("app_permission_button_deny"))
+ PermissionState.DENIED_WITH_PREJUDICE -> By.text(
+ getPermissionControllerString("app_permission_button_deny"))
+ }
+ } else if (isTv || isWatch) {
+ when (state) {
+ PermissionState.ALLOWED ->
+ if (showsForegroundOnlyButton(permission)) {
+ By.text(getPermissionControllerString(
+ ALLOW_FOREGROUND_PREFERENCE_TEXT
+ ))
+ } else {
+ byAnyText(getPermissionControllerResString(ALLOW_BUTTON_TEXT),
+ getPermissionControllerResString(ALLOW_ALL_FILES_BUTTON_TEXT))
+ }
+ PermissionState.DENIED ->
+ if (!isLegacyApp && hasAskButton(permission)) {
+ By.text(getPermissionControllerString(ASK_BUTTON_TEXT))
+ } else {
+ By.text(getPermissionControllerString(DENY_BUTTON_TEXT))
+ }
+ PermissionState.DENIED_WITH_PREJUDICE -> By.text(
+ getPermissionControllerString(DENY_BUTTON_TEXT))
+ }
+ } else {
+ when (state) {
+ PermissionState.ALLOWED ->
+ if (showsForegroundOnlyButton(permission)) {
+ By.res(ALLOW_FOREGROUND_RADIO_BUTTON)
+ } else if (showsAlwaysButton(permission)) {
+ By.res(ALLOW_ALWAYS_RADIO_BUTTON)
+ } else {
+ By.res(ALLOW_RADIO_BUTTON)
+ }
+ PermissionState.DENIED ->
+ if (!isLegacyApp && hasAskButton(permission)) {
+ By.res(ASK_RADIO_BUTTON)
+ } else {
+ By.res(DENY_RADIO_BUTTON)
+ }
+ PermissionState.DENIED_WITH_PREJUDICE -> By.res(DENY_RADIO_BUTTON)
+ }
+ }
+ )
+ alreadyChecked = button.isChecked
+ if (!alreadyChecked) {
+ button.click()
+ }
+
+ val shouldShowStorageWarning = SdkLevel.isAtLeastT() &&
+ getTargetSdk() <= Build.VERSION_CODES.S_V2 &&
+ permission in MEDIA_PERMISSIONS
+ if (shouldShowStorageWarning) {
+ click(By.res(ALERT_DIALOG_OK_BUTTON))
+ } else if (!alreadyChecked && isLegacyApp && wasGranted) {
+ if (!isTv) {
+ // Wait for alert dialog to popup, then scroll to the bottom of it
+ if (isWatch) {
+ waitFindObject(By.text(
+ getPermissionControllerString("old_sdk_deny_warning")))
+ } else {
+ waitFindObject(By.res(ALERT_DIALOG_MESSAGE))
+ }
+ scrollToBottom()
+ }
+
+ // Due to the limited real estate, Wear uses buttons with icons instead of text
+ // for dialogs
+ if (isWatch) {
+ click(By.res(
+ "com.android.permissioncontroller:id/wear_alertdialog_positive_button"))
+ } else {
+ val resources = context.createPackageContext(
+ packageManager.permissionControllerPackageName, 0
+ ).resources
+ val confirmTextRes = resources.getIdentifier(
+ "com.android.permissioncontroller:string/grant_dialog_button_deny_anyway",
+ null, null
+ )
+
+ val confirmText = resources.getString(confirmTextRes)
+ click(byTextStartsWithCaseInsensitive(confirmText))
+ }
+ }
+ pressBack()
+ }
+ pressBack()
+ pressBack()
+ }
+
+ private fun getPermissionLabel(permission: String): String {
+ val labelResName = permissionToLabelResNameMap[permission]
+ assertNotNull("Unknown permission $permission", labelResName)
+ val labelRes = platformResources.getIdentifier(labelResName, null, null)
+ return platformResources.getString(labelRes)
+ }
+
+ private fun hasAskButton(permission: String): Boolean =
+ when (permission) {
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.RECORD_AUDIO,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION -> true
+ else -> false
+ }
+ private fun showsAllowPhotosButton(permission: String): Boolean {
+ if (!isPhotoPickerPermissionPromptEnabled()) {
+ return false
+ }
+ return when (permission) {
+ Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED,
+ Manifest.permission.READ_MEDIA_IMAGES,
+ Manifest.permission.READ_MEDIA_VIDEO -> true
+ else -> false
+ }
+ }
+
+ private fun showsForegroundOnlyButton(permission: String): Boolean =
+ when (permission) {
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.RECORD_AUDIO -> true
+ else -> false
+ }
+
+ private fun showsAlwaysButton(permission: String): Boolean =
+ when (permission) {
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION -> true
+ else -> false
+ }
+
+ private fun scrollToBottom() {
+ val scrollable = UiScrollable(UiSelector().scrollable(true)).apply {
+ if (isWatch) {
+ swipeDeadZonePercentage = 0.1
+ } else {
+ swipeDeadZonePercentage = 0.25
+ }
+ }
+ waitForIdle()
+ if (scrollable.exists()) {
+ try {
+ scrollable.flingToEnd(10)
+ } catch (e: UiObjectNotFoundException) {
+ // flingToEnd() sometimes still fails despite waitForIdle() and the exists() check
+ // (b/246984354).
+ e.printStackTrace()
+ }
+ }
+ }
+
+ private fun byTextRes(textRes: Int): BySelector = By.text(context.getString(textRes))
+
+ private fun byTextStartsWithCaseInsensitive(prefix: String): BySelector =
+ By.text(Pattern.compile("(?i)^${Pattern.quote(prefix)}.*$"))
+
+ protected fun assertAppHasPermission(permissionName: String, expectPermission: Boolean) {
+ val checkPermissionResult = packageManager.checkPermission(permissionName, APP_PACKAGE_NAME)
+ assertTrue(
+ "Invalid permission check result: $checkPermissionResult",
+ checkPermissionResult == PackageManager.PERMISSION_GRANTED ||
+ checkPermissionResult == PackageManager.PERMISSION_DENIED
+ )
+ if (!expectPermission && checkPermissionResult == PackageManager.PERMISSION_GRANTED) {
+ Assert.fail("Unexpected permission check result for $permissionName: " +
+ "expected -1 (PERMISSION_DENIED) but was 0 (PERMISSION_GRANTED)")
+ }
+ if (expectPermission && checkPermissionResult == PackageManager.PERMISSION_DENIED) {
+ Assert.fail("Unexpected permission check result for $permissionName: " +
+ "expected 0 (PERMISSION_GRANTED) but was -1 (PERMISSION_DENIED)")
+ }
+ }
+
+ protected fun assertAppHasCalendarAccess(expectAccess: Boolean) {
+ val future = startActivityForFuture(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.CheckCalendarAccessActivity"
+ )
+ }
+ )
+ clickNotificationPermissionRequestAllowButtonIfAvailable()
+ val result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ assertEquals(Activity.RESULT_OK, result.resultCode)
+ assertTrue(result.resultData!!.hasExtra("$APP_PACKAGE_NAME.HAS_ACCESS"))
+ assertEquals(
+ expectAccess,
+ result.resultData!!.getBooleanExtra("$APP_PACKAGE_NAME.HAS_ACCESS", false)
+ )
+ }
+
+ protected fun assertPermissionFlags(permName: String, vararg flags: Pair<Int, Boolean>) {
+ val user = Process.myUserHandle()
+ SystemUtil.runWithShellPermissionIdentity {
+ val currFlags =
+ packageManager.getPermissionFlags(permName, APP_PACKAGE_NAME, user)
+ for ((flag, set) in flags) {
+ assertEquals("flag $flag: ", set, currFlags and flag != 0)
+ }
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt
new file mode 100644
index 000000000..b31ecc5ed
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.Manifest
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.app.compat.CompatChanges
+import android.content.AttributionSource
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.hardware.camera2.CameraManager
+import android.os.Build
+import android.os.Process
+import android.os.SystemClock
+import android.os.SystemProperties
+import android.permission.PermissionManager
+import android.platform.test.annotations.AsbSecurityTest
+import android.provider.DeviceConfig
+import android.provider.Settings
+import android.safetycenter.SafetyCenterManager
+import android.server.wm.WindowManagerStateHelper
+import androidx.annotation.RequiresApi
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.StaleObjectException
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.UiSelector
+import com.android.compatibility.common.util.CddTest
+import com.android.compatibility.common.util.DisableAnimationRule
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.UiAutomatorUtils2
+import com.android.modules.utils.build.SdkLevel
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase
+import java.util.regex.Pattern
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+private const val APK_PATH =
+ "/data/local/tmp/cts-permissionui/CtsAppThatAccessesMicAndCameraPermission.apk"
+private const val APP_LABEL = "CtsCameraMicAccess"
+private const val APP_PKG = "android.permissionui.cts.appthataccessescameraandmic"
+private const val SHELL_PKG = "com.android.shell"
+private const val USE_CAMERA = "use_camera"
+private const val USE_MICROPHONE = "use_microphone"
+private const val USE_HOTWORD = "use_hotword"
+private const val FINISH_EARLY = "finish_early"
+private const val USE_INTENT_ACTION = "test.action.USE_CAMERA_OR_MIC"
+private const val PRIVACY_CHIP_ID = "com.android.systemui:id/privacy_chip"
+private const val PRIVACY_ITEM_ID = "com.android.systemui:id/privacy_item"
+private const val INDICATORS_FLAG = "camera_mic_icons_enabled"
+private const val PERMISSION_INDICATORS_NOT_PRESENT = 162547999L
+private const val IDLE_TIMEOUT_MILLIS: Long = 1000
+private const val UNEXPECTED_TIMEOUT_MILLIS = 1000L
+private const val TIMEOUT_MILLIS: Long = 20000
+private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator"
+private const val MIC_LABEL_NAME = "microphone_toggle_label_qs"
+private const val CAMERA_LABEL_NAME = "camera_toggle_label_qs"
+private val HOTWORD_DETECTION_SERVICE_REQUIRED =
+ SystemProperties.getBoolean("ro.hotword.detection_service_required", false)
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@FlakyTest
+class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase {
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = instrumentation.context
+ private val uiAutomation: UiAutomation = instrumentation.uiAutomation
+ private val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
+ private val packageManager: PackageManager = context.packageManager
+ private val permissionManager: PermissionManager =
+ context.getSystemService(PermissionManager::class.java)!!
+
+ private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ private val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ private val safetyCenterMicLabel = getPermissionControllerString(MIC_LABEL_NAME)
+ private val safetyCenterCameraLabel = getPermissionControllerString(CAMERA_LABEL_NAME)
+ private val originalCameraLabel = packageManager.getPermissionGroupInfo(
+ Manifest.permission_group.CAMERA, 0).loadLabel(packageManager).toString()
+ private val originalMicLabel = packageManager.getPermissionGroupInfo(
+ Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
+ private val cameraLabel = originalCameraLabel.lowercase()
+ private val micLabel = originalMicLabel.lowercase()
+ private var wasEnabled = false
+ private var isScreenOn = false
+ private var screenTimeoutBeforeTest: Long = 0L
+ private lateinit var carMicPrivacyChipId: String
+ private lateinit var carCameraPrivacyChipId: String
+
+ @get:Rule
+ val disableAnimationRule = DisableAnimationRule()
+
+ constructor() : super()
+
+ companion object {
+ private const val AUTO_MIC_INDICATOR_DISMISSAL_TIMEOUT_MS = 30_000L
+ const val SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
+ const val DELAY_MILLIS = 3000L
+ }
+
+ private val safetyCenterEnabled = callWithShellPermissionIdentity {
+ DeviceConfig.getString(DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_CENTER_ENABLED, false.toString())!!
+ }
+
+ private fun uninstall() {
+ val output = runShellCommand("pm uninstall $APP_PKG").trim()
+ assertEquals("Success", output)
+ }
+
+ private fun install() {
+ val output = runShellCommandOrThrow("pm install -g $APK_PATH").trim()
+ assertEquals("Success", output)
+ }
+
+ @Before
+ fun setUp() {
+ runWithShellPermissionIdentity {
+ screenTimeoutBeforeTest = Settings.System.getLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT
+ )
+ Settings.System.putLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 1800000L
+ )
+ }
+
+ if (!isScreenOn) {
+ uiDevice.wakeUp()
+ runShellCommand(instrumentation, "wm dismiss-keyguard")
+ Thread.sleep(DELAY_MILLIS)
+ isScreenOn = true
+ }
+ uiDevice.findObject(By.text("Close"))?.click()
+ wasEnabled = setIndicatorsEnabledStateIfNeeded(true)
+ // If the change Id is not present, then isChangeEnabled will return true. To bypass this,
+ // the change is set to "false" if present.
+ assumeFalse("feature not present on this device", callWithShellPermissionIdentity {
+ CompatChanges.isChangeEnabled(PERMISSION_INDICATORS_NOT_PRESENT, Process.SYSTEM_UID)
+ })
+ install()
+ }
+
+ private fun setIndicatorsEnabledStateIfNeeded(shouldBeEnabled: Boolean): Boolean {
+ var currentlyEnabled = false
+ runWithShellPermissionIdentity {
+ currentlyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ INDICATORS_FLAG, true)
+ if (currentlyEnabled != shouldBeEnabled) {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG,
+ shouldBeEnabled.toString(), false)
+ }
+ }
+ return currentlyEnabled
+ }
+
+ @After
+ fun tearDown() {
+ uninstall()
+ if (isCar) {
+ // Deselect the indicator since it persists otherwise
+ pressBack()
+ }
+ eventually({
+ assertIndicatorsShown(false, false, false)
+ }, AUTO_MIC_INDICATOR_DISMISSAL_TIMEOUT_MS)
+ if (!wasEnabled) {
+ setIndicatorsEnabledStateIfNeeded(false)
+ }
+ runWithShellPermissionIdentity {
+ Settings.System.putLong(
+ context.contentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
+ screenTimeoutBeforeTest
+ )
+ }
+ changeSafetyCenterFlag(safetyCenterEnabled)
+ if (!isTv) {
+ pressBack()
+ pressBack()
+ }
+ pressHome()
+ pressHome()
+ }
+
+ private fun openApp(
+ useMic: Boolean,
+ useCamera: Boolean,
+ useHotword: Boolean,
+ finishEarly: Boolean = false
+ ) {
+ context.startActivity(Intent(USE_INTENT_ACTION).apply {
+ putExtra(USE_CAMERA, useCamera)
+ putExtra(USE_MICROPHONE, useMic)
+ putExtra(USE_HOTWORD, useHotword)
+ putExtra(FINISH_EARLY, finishEarly)
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ })
+ }
+
+ @Test
+ @CddTest(requirement = "9.8.2/H-5-1,T-5-1,A-2-1")
+ fun testCameraIndicator() {
+ // If camera is not available skip the test
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ val manager = context.getSystemService(CameraManager::class.java)!!
+ assumeTrue(manager.cameraIdList.isNotEmpty())
+ changeSafetyCenterFlag(false.toString())
+ testCameraAndMicIndicator(useMic = false, useCamera = true)
+ }
+
+ @Test
+ @CddTest(requirement = "9.8.2/H-4-1,T-4-1,A-1-1")
+ fun testMicIndicator() {
+ changeSafetyCenterFlag(false.toString())
+ testCameraAndMicIndicator(useMic = true, useCamera = false)
+ }
+
+ // TODO b/269687722: remove once mainline presubmit uses a more recent S build
+ @Test
+ @AsbSecurityTest(cveBugId = [258672042])
+ fun testMicIndicatorWithManualFinishOpStillShows() {
+ changeSafetyCenterFlag(false.toString())
+ testCameraAndMicIndicator(useMic = true, useCamera = false, finishEarly = true)
+ }
+
+ @Test
+ @CddTest(requirement = "9.8.2/H-4-1,T-4-1,A-1-1")
+ fun testHotwordIndicatorBehavior() {
+ changeSafetyCenterFlag(false.toString())
+ testCameraAndMicIndicator(useMic = false, useCamera = false, useHotword = true)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ fun testChainUsageWithOtherUsage() {
+ // TV has only the mic icon
+ assumeFalse(isTv)
+ // Car has separate panels for mic and camera for now.
+ // TODO(b/218788634): enable this test for car once the new camera indicator is implemented.
+ assumeFalse(isCar)
+ // If camera is not available skip the test
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ changeSafetyCenterFlag(false.toString())
+ testCameraAndMicIndicator(useMic = false, useCamera = true, chainUsage = true)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ fun testSafetyCenterCameraIndicator() {
+ assumeFalse(isTv)
+ assumeFalse(isCar)
+ val manager = context.getSystemService(CameraManager::class.java)!!
+ assumeTrue(manager.cameraIdList.isNotEmpty())
+ changeSafetyCenterFlag(true.toString())
+ assumeSafetyCenterEnabled()
+ testCameraAndMicIndicator(useMic = false, useCamera = true, safetyCenterEnabled = true)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ fun testSafetyCenterMicIndicator() {
+ assumeFalse(isTv)
+ assumeFalse(isCar)
+ changeSafetyCenterFlag(true.toString())
+ assumeSafetyCenterEnabled()
+ testCameraAndMicIndicator(useMic = true, useCamera = false, safetyCenterEnabled = true)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ fun testSafetyCenterHotwordIndicatorBehavior() {
+ assumeFalse(isTv)
+ assumeFalse(isCar)
+ assumeTrue(HOTWORD_DETECTION_SERVICE_REQUIRED)
+ changeSafetyCenterFlag(true.toString())
+ assumeSafetyCenterEnabled()
+ testCameraAndMicIndicator(
+ useMic = false,
+ useCamera = false,
+ useHotword = true,
+ safetyCenterEnabled = true
+ )
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ fun testSafetyCenterChainUsageWithOtherUsage() {
+ assumeFalse(isTv)
+ assumeFalse(isCar)
+ changeSafetyCenterFlag(true.toString())
+ assumeSafetyCenterEnabled()
+ testCameraAndMicIndicator(
+ useMic = false,
+ useCamera = true,
+ chainUsage = true,
+ safetyCenterEnabled = true
+ )
+ }
+
+ private fun testCameraAndMicIndicator(
+ useMic: Boolean,
+ useCamera: Boolean,
+ useHotword: Boolean = false,
+ chainUsage: Boolean = false,
+ safetyCenterEnabled: Boolean = false,
+ finishEarly: Boolean = false
+ ) {
+ // If camera is not available skip the test
+ if (useCamera) {
+ assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA))
+ }
+ var chainAttribution: AttributionSource? = null
+ openApp(useMic, useCamera, useHotword, finishEarly)
+ try {
+ eventually {
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+ assertTrue("View with text $APP_LABEL not found", appView.exists())
+ }
+ if (chainUsage) {
+ chainAttribution = createChainAttribution()
+ runWithShellPermissionIdentity {
+ val ret = permissionManager.checkPermissionForStartDataDelivery(
+ Manifest.permission.RECORD_AUDIO, chainAttribution!!, "")
+ assertEquals(PermissionManager.PERMISSION_GRANTED, ret)
+ }
+ }
+
+ assertIndicatorsShown(useMic, useCamera, useHotword, chainUsage,
+ safetyCenterEnabled)
+
+ if (finishEarly) {
+ // Assert that the indicator doesn't go away
+ val indicatorGoneException: Exception? = try {
+ eventually {
+ assertIndicatorsShown(false, false, false)
+ }
+ null
+ } catch (e: Exception) {
+ e
+ }
+ assertNotNull("Expected the indicator to be present", indicatorGoneException)
+ }
+ } finally {
+ if (chainAttribution != null) {
+ runWithShellPermissionIdentity {
+ permissionManager.finishDataDelivery(Manifest.permission.RECORD_AUDIO,
+ chainAttribution)
+ }
+ }
+ }
+ }
+
+ private fun assertIndicatorsShown(
+ useMic: Boolean,
+ useCamera: Boolean,
+ useHotword: Boolean = false,
+ chainUsage: Boolean = false,
+ safetyCenterEnabled: Boolean = false,
+ ) {
+ if (isTv) {
+ assertTvIndicatorsShown(useMic, useCamera, useHotword)
+ } else if (isCar) {
+ assertCarIndicatorsShown(useMic, useCamera, useHotword, chainUsage)
+ } else {
+ uiDevice.openQuickSettings()
+ val micInUse = if (SdkLevel.isAtLeastU() && HOTWORD_DETECTION_SERVICE_REQUIRED) {
+ useMic || useHotword
+ } else {
+ useMic
+ }
+ assertPrivacyChipAndIndicatorsPresent(micInUse, useCamera, chainUsage,
+ safetyCenterEnabled)
+ uiDevice.pressBack()
+ }
+ }
+
+ private fun assertTvIndicatorsShown(useMic: Boolean, useCamera: Boolean, useHotword: Boolean) {
+ if (useMic || useHotword || (!useMic && !useCamera && !useHotword)) {
+ eventually {
+ val found = WindowManagerStateHelper()
+ .waitFor("Waiting for the mic indicator window to come up") {
+ it.containsWindow(TV_MIC_INDICATOR_WINDOW_TITLE) &&
+ it.isWindowVisible(TV_MIC_INDICATOR_WINDOW_TITLE)
+ }
+ if (useMic) {
+ assertTrue("Did not find chip", found)
+ } else {
+ assertFalse("Found chip, but did not expect to", found)
+ }
+ }
+ }
+ if (useCamera) {
+ // There is no camera indicator on TVs.
+ }
+ }
+
+ private fun assertCarIndicatorsShown(
+ useMic: Boolean,
+ useCamera: Boolean,
+ useHotword: Boolean,
+ chainUsage: Boolean
+ ) {
+ eventually {
+ // Ensure the privacy chip is present (or not)
+ carMicPrivacyChipId = context.getString(R.string.car_mic_privacy_chip_id)
+ carCameraPrivacyChipId = context.getString(R.string.car_camera_privacy_chip_id)
+ var micPrivacyChip = uiDevice.findObject(By.res(carMicPrivacyChipId))
+ var cameraPrivacyChip = uiDevice.findObject(By.res(carCameraPrivacyChipId))
+ if (useMic) {
+ assertNotNull("Did not find mic chip", micPrivacyChip)
+ // Click to chip to show the panel.
+ micPrivacyChip.click()
+ } else if (useCamera) {
+ assertNotNull("Did not find camera chip", cameraPrivacyChip)
+ // Click to chip to show the panel.
+ cameraPrivacyChip.click()
+ } else {
+ assertNull("Found mic chip, but did not expect to", micPrivacyChip)
+ assertNull("Found camera chip, but did not expect to", cameraPrivacyChip)
+ }
+ }
+
+ eventually {
+ if (chainUsage) {
+ // Not applicable for car
+ assertChainMicAndOtherCameraUsed(false)
+ return@eventually
+ }
+ if (useMic) {
+ // There should be a mic privacy panel after mic privacy chip is clicked
+ val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
+ assertTrue("View with text $micLabel not found", micLabelView.exists())
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+ assertTrue("View with text $APP_LABEL not found", appView.exists())
+ } else if (useCamera) {
+ // There should be a camera privacy panel after camera privacy chip is clicked
+ val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
+ assertTrue("View with text $cameraLabel not found", cameraLabelView.exists())
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+ assertTrue("View with text $APP_LABEL not found", appView.exists())
+ } else {
+ // There should be no privacy panel when using hot word
+ val micLabelView = uiDevice.findObject(UiSelector().textContains(micLabel))
+ assertFalse("View with text $micLabel found, but did not expect to",
+ micLabelView.exists())
+ val cameraLabelView = uiDevice.findObject(UiSelector().textContains(cameraLabel))
+ assertFalse("View with text $cameraLabel found, but did not expect to",
+ cameraLabelView.exists())
+ val appView = uiDevice.findObject(UiSelector().textContains(APP_LABEL))
+ assertFalse("View with text $APP_LABEL found, but did not expect to",
+ appView.exists())
+ }
+ }
+ }
+
+ private fun assertPrivacyChipAndIndicatorsPresent(
+ useMic: Boolean,
+ useCamera: Boolean,
+ chainUsage: Boolean,
+ safetyCenterEnabled: Boolean = false
+ ) {
+ // Ensure the privacy chip is present
+ if (useCamera || useMic) {
+ eventually {
+ val privacyChip = UiAutomatorUtils2.waitFindObjectOrNull(By.res(PRIVACY_CHIP_ID))
+ assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip)
+ privacyChip.click()
+ }
+ } else {
+ UiAutomatorUtils2.waitUntilObjectGone(By.res(PRIVACY_CHIP_ID))
+ return
+ }
+
+ eventually {
+ if (chainUsage) {
+ assertChainMicAndOtherCameraUsed(safetyCenterEnabled)
+ return@eventually
+ }
+ if (useMic) {
+ if (safetyCenterEnabled) {
+ assertSafetyCenterMicViewNotNull()
+ } else {
+ val iconView = waitFindObject(By.descContains(micLabel))
+ assertNotNull("View with description '$micLabel' not found", iconView)
+ }
+ }
+ if (useCamera) {
+ if (safetyCenterEnabled) {
+ assertSafetyCenterCameraViewNotNull()
+ } else {
+ val iconView = waitFindObject(By.descContains(cameraLabel))
+ assertNotNull("View with description '$cameraLabel' not found", iconView)
+ }
+ }
+ var appView = waitFindObject(By.textContains(APP_LABEL))
+ assertNotNull("View with text $APP_LABEL not found", appView)
+ }
+ uiDevice.pressBack()
+ }
+
+ private fun createChainAttribution(): AttributionSource? {
+ var attrSource: AttributionSource? = null
+ runWithShellPermissionIdentity {
+ try {
+ val appUid = packageManager.getPackageUid(APP_PKG, 0)
+ val childAttribution = AttributionSource(appUid, APP_PKG, null)
+ val attribution = AttributionSource(Process.myUid(), context.packageName, null,
+ null, permissionManager.registerAttributionSource(childAttribution))
+ attrSource = permissionManager.registerAttributionSource(attribution)
+ } catch (e: PackageManager.NameNotFoundException) {
+ Assert.fail("Expected to find a UID for $APP_LABEL")
+ }
+ }
+ return attrSource
+ }
+
+ private fun assertChainMicAndOtherCameraUsed(safetyCenterEnabled: Boolean) {
+ val shellLabel = try {
+ context.packageManager.getApplicationInfo(SHELL_PKG, 0)
+ .loadLabel(context.packageManager).toString()
+ } catch (e: PackageManager.NameNotFoundException) {
+ "Did not find shell package"
+ }
+
+ if (safetyCenterEnabled) {
+ assertSafetyCenterMicViewNotNull()
+ assertSafetyCenterCameraViewNotNull()
+ var shellView = waitFindObject(By.textContains(shellLabel))
+ assertNotNull("View with text $shellLabel not found", shellView)
+ } else {
+ val usageViews = uiDevice.findObjects(By.res(PRIVACY_ITEM_ID))
+ assertEquals("Expected two usage views", 2, usageViews.size)
+ val appViews = uiDevice.findObjects(By.textContains(APP_LABEL))
+ assertEquals("Expected two $APP_LABEL view", 2, appViews.size)
+ val shellView = uiDevice.findObjects(By.textContains(shellLabel))
+ assertEquals("Expected only one shell view", 1, shellView.size)
+ }
+ }
+
+ private fun pressBack() {
+ uiDevice.pressBack()
+ }
+
+ private fun pressHome() {
+ uiDevice.pressHome()
+ }
+
+ private fun changeSafetyCenterFlag(safetyCenterEnabled: String) {
+ runWithShellPermissionIdentity {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_CENTER_ENABLED, safetyCenterEnabled, false)
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private fun assumeSafetyCenterEnabled() {
+ val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
+ val isSafetyCenterEnabled: Boolean = runWithShellPermissionIdentity<Boolean> {
+ safetyCenterManager.isSafetyCenterEnabled
+ }
+ assumeTrue(isSafetyCenterEnabled)
+ }
+
+ protected fun waitFindObject(selector: BySelector): UiObject2? {
+ return findObjectWithRetry({ t -> UiAutomatorUtils2.waitFindObject(selector, t) })
+ }
+
+ private fun findObjectWithRetry(
+ automatorMethod: (timeoutMillis: Long) -> UiObject2?,
+ timeoutMillis: Long = TIMEOUT_MILLIS
+ ): UiObject2? {
+ val startTime = SystemClock.elapsedRealtime()
+ return try {
+ automatorMethod(timeoutMillis)
+ } catch (e: StaleObjectException) {
+ val remainingTime = timeoutMillis - (SystemClock.elapsedRealtime() - startTime)
+ if (remainingTime <= 0) {
+ throw e
+ }
+ automatorMethod(remainingTime)
+ }
+ }
+
+ private fun getPermissionControllerString(resourceName: String): String {
+ val permissionControllerPkg = context.packageManager.permissionControllerPackageName
+ try {
+ val permissionControllerContext =
+ context.createPackageContext(permissionControllerPkg, 0)
+ val resourceId =
+ permissionControllerContext.resources.getIdentifier(
+ resourceName, "string", "com.android.permissioncontroller")
+ return permissionControllerContext.getString(resourceId)
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw RuntimeException(e)
+ }
+ }
+
+ private fun assertSafetyCenterMicViewNotNull() {
+ val micView = waitFindObject(byOneOfText(originalMicLabel, safetyCenterMicLabel))
+ assertNotNull(
+ "View with text '$originalMicLabel' or '$safetyCenterMicLabel' not found", micView)
+ }
+
+ private fun assertSafetyCenterCameraViewNotNull() {
+ val cameraView = waitFindObject(byOneOfText(originalCameraLabel, safetyCenterCameraLabel))
+ assertNotNull(
+ "View with text '$originalCameraLabel' or '$safetyCenterCameraLabel' not found",
+ cameraView)
+ }
+
+ private fun byOneOfText(vararg textValues: String) =
+ By.text(Pattern.compile(textValues.joinToString(separator = "|") { Pattern.quote(it) }))
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/LocationAccuracyTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/LocationAccuracyTest.kt
new file mode 100644
index 000000000..e515a7604
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/LocationAccuracyTest.kt
@@ -0,0 +1,168 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import com.android.modules.utils.build.SdkLevel
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+
+@FlakyTest
+class LocationAccuracyTest : BaseUsePermissionTest() {
+
+ companion object {
+ private const val LOCATION_ACCURACY_PRECISE_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/permission_location_accuracy_radio_fine"
+ private const val LOCATION_ACCURACY_COARSE_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/permission_location_accuracy_radio_coarse"
+ private const val LOCATION_ACCURACY_PRECISE_ONLY_VIEW =
+ "com.android.permissioncontroller:id/permission_location_accuracy_fine_only"
+ private const val LOCATION_ACCURACY_COARSE_ONLY_VIEW =
+ "com.android.permissioncontroller:id/permission_location_accuracy_coarse_only"
+ }
+
+ @Before
+ fun setup() {
+ assumeTrue("Location Accuracy is only available on S+", SdkLevel.isAtLeastS())
+ assumeFalse(isAutomotive)
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ }
+
+ @Test
+ fun testCoarsePermissionIsGranted() {
+ installPackage(APP_APK_PATH_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to false,
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickCoarseLocationRadioButton()
+ clickPreciseLocationRadioButton()
+ clickCoarseLocationRadioButton()
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+
+ @Test
+ fun testPrecisePermissionIsGranted() {
+ installPackage(APP_APK_PATH_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to true,
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickPreciseLocationRadioButton()
+ clickCoarseLocationRadioButton()
+ clickPreciseLocationRadioButton()
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+
+ @Test
+ fun testPermissionUpgradeFlow() {
+ installPackage(APP_APK_PATH_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to false,
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickCoarseLocationRadioButton()
+ clickPreciseLocationRadioButton()
+ clickCoarseLocationRadioButton()
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ // now request again to change to precise location
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to true,
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickPreciseLocationOnlyView()
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+
+ @Test
+ fun testCoarseRequestAndGrant() {
+ installPackage(APP_APK_PATH_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickCoarseLocationOnlyView()
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+ }
+
+ @Test
+ fun testPreSAppsAutograntFineIfCoarseGranted() {
+ installPackage(APP_APK_PATH_30)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ requestAppPermissionsAndAssertResult(
+ ACCESS_COARSE_LOCATION to true
+ ) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to true,
+ waitForWindowTransition = false
+ ) { }
+ }
+
+ private fun clickPreciseLocationRadioButton() {
+ click(By.res(LOCATION_ACCURACY_PRECISE_RADIO_BUTTON))
+ }
+
+ private fun clickCoarseLocationRadioButton() {
+ click(By.res(LOCATION_ACCURACY_COARSE_RADIO_BUTTON))
+ }
+
+ private fun clickPreciseLocationOnlyView() {
+ click(By.res(LOCATION_ACCURACY_PRECISE_ONLY_VIEW))
+ }
+
+ private fun clickCoarseLocationOnlyView() {
+ click(By.res(LOCATION_ACCURACY_COARSE_ONLY_VIEW))
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/LocationProviderInterceptDialogTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/LocationProviderInterceptDialogTest.kt
new file mode 100644
index 000000000..3dd2a8008
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/LocationProviderInterceptDialogTest.kt
@@ -0,0 +1,148 @@
+/*
+ * 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.permissionui.cts
+
+import android.app.Activity
+import android.app.AppOpsManager
+import android.content.ComponentName
+import android.content.Intent
+import android.location.LocationManager
+import android.os.Build
+import android.permission.cts.MtsIgnore
+import android.permission.cts.PermissionUtils
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.AppOpsUtils
+import com.android.compatibility.common.util.CddTest
+import com.android.compatibility.common.util.SystemUtil
+import java.util.concurrent.TimeUnit
+import org.junit.Assert
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Test
+
+private const val EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME"
+private const val ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS"
+
+/**
+ * Tests that LocationProviderInterceptDialog (a warning dialog) shows when attempting to view the
+ * location permission for location a service provider app (e.g., usually GMS, but we use a custom
+ * app in this test).
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+@FlakyTest
+@CddTest(requirement = "9.1/C-0-1")
+class LocationProviderInterceptDialogTest : BaseUsePermissionTest() {
+ @Before
+ fun setup() {
+ assumeFalse(isAutomotive)
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ installPackage(MIC_LOCATION_PROVIDER_APP_APK_PATH, grantRuntimePermissions = true)
+ AppOpsUtils.setOpMode(
+ MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME,
+ AppOpsManager.OPSTR_MOCK_LOCATION,
+ AppOpsManager.MODE_ALLOWED)
+ enableMicrophoneAppAsLocationProvider()
+ }
+
+ @Test
+ @Ignore("b/288471744")
+ @MtsIgnore(bugId = 288471744)
+ fun clickLocationPermission_showDialog_clickOk() {
+ openPermissionScreenForApp()
+ clickAndWaitForWindowTransition(By.text("Location"))
+ findView(
+ By.textContains("Location access can be modified from location settings"),
+ true)
+ click(By.res(OK_BUTTON_RES))
+ }
+
+ @Test
+ @Ignore("b/288471744")
+ @MtsIgnore(bugId = 288471744)
+ fun clickLocationPermission_showDialog_clickLocationAccess() {
+ openPermissionScreenForApp()
+ clickAndWaitForWindowTransition(By.text("Location"))
+ findView(
+ By.textContains("Location access can be modified from location settings"),
+ true)
+ clickAndWaitForWindowTransition(By.res(LOCATION_ACCESS_BUTTON_RES))
+ findView(By.res(USE_LOCATION_LABEL_ID), true)
+ }
+
+ @Test
+ @Ignore("b/288471744")
+ @MtsIgnore(bugId = 288471744)
+ fun checkRestrictedPermissions() {
+ context.sendBroadcast(Intent(PermissionTapjackingTest.ACTION_SHOW_OVERLAY)
+ .putExtra("package", MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
+ .putExtra("permission", "android.permission.BACKGROUND_CAMERA"))
+ }
+
+ private fun openPermissionScreenForApp() {
+ restartPermissionController()
+ doAndWaitForWindowTransition {
+ SystemUtil.runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(ACTION_MANAGE_APP_PERMISSIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ putExtra(EXTRA_PACKAGE_NAME, MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
+ }
+ )
+ }
+ }
+ }
+
+ private fun restartPermissionController() {
+ PermissionUtils.clearAppState(permissionControllerPackageName)
+ }
+
+ private fun enableMicrophoneAppAsLocationProvider() {
+ val locationManager = context.getSystemService(LocationManager::class.java)!!
+ val future =
+ startActivityForFuture(
+ Intent().apply {
+ component =
+ ComponentName(
+ MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME,
+ "$MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME.AddLocationProviderActivity")
+ })
+ val result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ Assert.assertEquals(Activity.RESULT_OK, result.resultCode)
+ Assert.assertTrue(
+ SystemUtil.callWithShellPermissionIdentity {
+ locationManager.isProviderPackage(MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME)
+ })
+ }
+
+ companion object {
+ private const val USE_LOCATION_LABEL_ID =
+ "com.android.settings:id/switch_text"
+ private const val MIC_LOCATION_PROVIDER_APP_APK_PATH =
+ "$APK_DIRECTORY/CtsAccessMicrophoneAppLocationProvider.apk"
+ private const val MIC_LOCATION_PROVIDER_APP_PACKAGE_NAME =
+ "android.permissionui.cts.accessmicrophoneapplocationprovider"
+ private const val OK_BUTTON_RES = "android:id/button2"
+ private const val LOCATION_ACCESS_BUTTON_RES = "android:id/button1"
+ private val permissionControllerPackageName =
+ context.packageManager.permissionControllerPackageName
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt
new file mode 100644
index 000000000..fef8a83c4
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt
@@ -0,0 +1,182 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest
+import android.os.Build
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.util.CddTest
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assume
+import org.junit.Test
+
+/**
+ * Tests media storage supergroup behavior. I.e., on a T+ platform, for legacy (targetSdk<T) apps,
+ * the storage permission groups (STORAGE, AURAL, and VISUAL) form a supergroup, which effectively
+ * treats them as one group and therefore their permission state must always be equal.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@CddTest(requirement = "9.1/C-0-1")
+@FlakyTest
+class MediaPermissionTest : BaseUsePermissionTest() {
+ private fun assertStorageAndMediaPermissionState(state: Boolean) {
+ for (permission in STORAGE_AND_MEDIA_PERMISSIONS) {
+ assertAppHasPermission(permission, state)
+ }
+ }
+
+ @Test
+ fun testWhenRESIsGrantedFromGrantDialogThenShouldGrantAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ requestAppPermissionsAndAssertResult(Manifest.permission.READ_EXTERNAL_STORAGE to true) {
+ clickPermissionRequestAllowButton()
+ }
+ assertStorageAndMediaPermissionState(true)
+ }
+
+ @Test
+ fun testWhenRESIsGrantedManuallyThenShouldGrantAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_EXTERNAL_STORAGE)
+ assertStorageAndMediaPermissionState(true)
+ }
+
+ @Test
+ fun testWhenAuralIsGrantedManuallyThenShouldGrantAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_MEDIA_AUDIO)
+ assertStorageAndMediaPermissionState(true)
+ }
+
+ @Test
+ fun testWhenVisualIsGrantedManuallyThenShouldGrantAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_MEDIA_VIDEO)
+ assertStorageAndMediaPermissionState(true)
+ }
+
+ @Test
+ fun testWhenRESIsDeniedFromGrantDialogThenShouldDenyAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ requestAppPermissionsAndAssertResult(Manifest.permission.READ_EXTERNAL_STORAGE to false) {
+ clickPermissionRequestDenyButton()
+ }
+ assertStorageAndMediaPermissionState(false)
+ }
+
+ @Test
+ fun testWhenRESIsDeniedManuallyThenShouldDenyAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_EXTERNAL_STORAGE)
+ assertStorageAndMediaPermissionState(true)
+ revokeAppPermissionsByUi(Manifest.permission.READ_EXTERNAL_STORAGE)
+ assertStorageAndMediaPermissionState(false)
+ }
+
+ @Test
+ fun testWhenAuralIsDeniedManuallyThenShouldDenyAllPermissions() {
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_MEDIA_AUDIO)
+ revokeAppPermissionsByUi(Manifest.permission.READ_MEDIA_AUDIO)
+ assertStorageAndMediaPermissionState(false)
+ }
+
+ @Test
+ fun testWhenVisualIsDeniedManuallyThenShouldDenyAllPermissions() {
+ // TODO: Re-enable after b/239249703 is fixed
+ Assume.assumeFalse("skip on TV due to flaky", isTv)
+ installPackage(APP_APK_PATH_23)
+ grantAppPermissionsByUi(Manifest.permission.READ_MEDIA_VIDEO)
+ revokeAppPermissionsByUi(Manifest.permission.READ_MEDIA_VIDEO)
+ assertStorageAndMediaPermissionState(false)
+ }
+
+ @Test
+ fun testWhenA33AppRequestsStorageThenNoDialogAndNoGrant() {
+ installPackage(APP_APK_PATH_MEDIA_PERMISSION_33_WITH_STORAGE)
+ requestAppPermissions(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ waitForWindowTransition = false
+ ) {
+ }
+ assertStorageAndMediaPermissionState(false)
+ }
+
+ @Test
+ fun testWhenA33AppRequestsAuralThenDialogAndGrant() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissions(Manifest.permission.READ_MEDIA_AUDIO) {
+ clickPermissionRequestAllowButton()
+ }
+ assertAppHasPermission(Manifest.permission.READ_EXTERNAL_STORAGE, false)
+ assertAppHasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, false)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_AUDIO, true)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_VIDEO, false)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_IMAGES, false)
+ }
+
+ @Test
+ fun testWhenA33AppRequestsVisualThenDialogAndGrant() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissions(
+ Manifest.permission.READ_MEDIA_VIDEO,
+ Manifest.permission.READ_MEDIA_IMAGES) {
+ if (isPhotoPickerPermissionPromptEnabled()) {
+ clickPermissionRequestAllowAllButton()
+ } else {
+ clickPermissionRequestAllowButton()
+ }
+ }
+ assertAppHasPermission(Manifest.permission.READ_EXTERNAL_STORAGE, false)
+ assertAppHasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, false)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_AUDIO, false)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_VIDEO, true)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_IMAGES, true)
+ }
+
+ @Test
+ fun testWhenA30AppRequestsStorageWhenMediaPermsHaveRWRFlag() {
+ installPackage(APP_APK_PATH_30)
+
+ requestAppPermissionsAndAssertResult(
+ Manifest.permission.READ_EXTERNAL_STORAGE to true
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+
+ fun setRevokeWhenRequested(permission: String) = SystemUtil.runShellCommandOrThrow(
+ "pm set-permission-flags android.permissionui.cts.usepermission " +
+ permission + " revoke-when-requested")
+ setRevokeWhenRequested("android.permission.READ_MEDIA_AUDIO")
+ setRevokeWhenRequested("android.permission.READ_MEDIA_VIDEO")
+ setRevokeWhenRequested("android.permission.READ_MEDIA_IMAGES")
+
+ requestAppPermissionsAndAssertResult(
+ Manifest.permission.READ_EXTERNAL_STORAGE to true,
+ waitForWindowTransition = false
+ ) {
+ // No dialog should appear
+ }
+
+ assertAppHasPermission(Manifest.permission.READ_EXTERNAL_STORAGE, true)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_AUDIO, true)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_VIDEO, true)
+ assertAppHasPermission(Manifest.permission.READ_MEDIA_IMAGES, true)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionUpgradeTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionUpgradeTest.kt
new file mode 100644
index 000000000..ceb1d170d
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionUpgradeTest.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.READ_EXTERNAL_STORAGE
+import android.Manifest.permission.READ_MEDIA_AUDIO
+import android.Manifest.permission.READ_MEDIA_IMAGES
+import android.Manifest.permission.READ_MEDIA_VIDEO
+import android.os.Build
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.util.CddTest
+import org.junit.Test
+
+/**
+ * Tests media storage permission behavior upon app upgrade.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@CddTest(requirement = "9.1/C-0-1")
+@FlakyTest
+class MediaPermissionUpgradeTest : BaseUsePermissionTest() {
+ @Test
+ fun testAfterUpgradeToTiramisuThenNoGrantDialogShownForMediaPerms() {
+ // Install 32
+ installPackage(APP_APK_PATH_32)
+
+ // Request STORAGE, and click allow
+ requestAppPermissionsAndAssertResult(
+ READ_EXTERNAL_STORAGE to true,
+ waitForWindowTransition = !isWatch
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+
+ // Upgrade 32 -> 33
+ installPackage(APP_APK_PATH_LATEST, reinstall = true)
+
+ // Request READ_MEDIA_*
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_AUDIO to true,
+ READ_MEDIA_VIDEO to true,
+ READ_MEDIA_IMAGES to true,
+ waitForWindowTransition = false
+ ) {
+ // Don't click any grant dialog buttons because no grant dialog should appear
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/MultiDevicePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/MultiDevicePermissionTest.kt
new file mode 100644
index 000000000..dc9a2ebf1
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/MultiDevicePermissionTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.Manifest
+import android.os.Build
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+/**
+ * This test validates multi device permission APIs.
+ *
+ * TODO(mrulhania): will update the test once all iris permission API changes are merged.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
+@FlakyTest
+class MultiDevicePermissionTest : BaseUsePermissionTest() {
+ @Before
+ fun setup() {
+ Assume.assumeFalse(isAutomotive)
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+ }
+
+ @Test
+ fun testPermissionGrantForDefaultDevice() {
+ installPackage(APP_APK_PATH_LATEST)
+ assertAppHasPermission(Manifest.permission.CAMERA, false)
+ assertAppHasPermission(Manifest.permission.RECORD_AUDIO, false)
+
+ requestAppPermissionsAndAssertResult(Manifest.permission.CAMERA to true) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ requestAppPermissionsAndAssertResult(Manifest.permission.RECORD_AUDIO to true) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/NoPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/NoPermissionTest.kt
new file mode 100644
index 000000000..a5d428812
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/NoPermissionTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts
+
+import android.app.Activity
+import androidx.test.filters.FlakyTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.modules.utils.build.SdkLevel
+import org.junit.Assume
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@FlakyTest
+class NoPermissionTest : BaseUsePermissionTest() {
+ @Test
+ fun testStartActivity22() {
+ Assume.assumeFalse(SdkLevel.isAtLeastT())
+ installPackage(APP_APK_PATH_22_NONE)
+
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {}
+
+ clearTargetSdkWarning()
+ }
+
+ @Test
+ fun testStartActivityLatest() {
+ installPackage(APP_APK_PATH_LATEST_NONE)
+
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {}
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/NotificationPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/NotificationPermissionTest.kt
new file mode 100644
index 000000000..4e62a62ad
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/NotificationPermissionTest.kt
@@ -0,0 +1,409 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.POST_NOTIFICATIONS
+import android.Manifest.permission.RECORD_AUDIO
+import android.app.ActivityOptions
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Context.RECEIVER_EXPORTED
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import android.os.Build
+import android.os.UserHandle
+import android.provider.Settings
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import java.util.concurrent.CountDownLatch
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+const val EXTRA_CREATE_CHANNELS = "extra_create"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
+const val EXTRA_START_SECOND_ACTIVITY = "extra_start_second_activity"
+const val EXTRA_START_SECOND_APP = "extra_start_second_app"
+const val ACTIVITY_LABEL = "CreateNotif"
+const val SECOND_ACTIVITY_LABEL = "EmptyActivity"
+const val ALLOW = "to send you"
+const val INTENT_ACTION = "usepermission.createchannels.MAIN"
+const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
+const val NOTIFICATION_PERMISSION_ENABLED = "notification_permission_enabled"
+const val EXPECTED_TIMEOUT_MS = 2000L
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@FlakyTest
+class NotificationPermissionTest : BaseUsePermissionTest() {
+
+ private val cr = callWithShellPermissionIdentity {
+ context.createContextAsUser(UserHandle.SYSTEM, 0).contentResolver
+ }
+ private var previousEnableState = -1
+ private var countDown: CountDownLatch = CountDownLatch(1)
+ private var allowedGroups = listOf<String>()
+ private val receiver: BroadcastReceiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ allowedGroups =
+ intent?.getStringArrayListExtra(
+ PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS
+ )
+ ?: emptyList()
+ countDown.countDown()
+ }
+ }
+
+ @Before
+ fun setLatchAndEnablePermission() {
+ // b/220968160: Notification permission is not enabled on TV devices.
+ assumeFalse(isTv)
+ runWithShellPermissionIdentity {
+ previousEnableState = Settings.Secure.getInt(cr, NOTIFICATION_PERMISSION_ENABLED, 0)
+ Settings.Secure.putInt(cr, NOTIFICATION_PERMISSION_ENABLED, 1)
+ }
+ countDown = CountDownLatch(1)
+ allowedGroups = listOf()
+ context.registerReceiver(receiver, IntentFilter(BROADCAST_ACTION), RECEIVER_EXPORTED)
+ }
+
+ @After
+ fun resetPermissionAndRemoveReceiver() {
+ if (previousEnableState >= 0) {
+ runWithShellPermissionIdentity {
+ Settings.Secure.putInt(cr, NOTIFICATION_PERMISSION_ENABLED, previousEnableState)
+ }
+ context.unregisterReceiver(receiver)
+ }
+ }
+
+ @Test
+ fun notificationPermissionAddedForLegacyApp() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ runWithShellPermissionIdentity {
+ Assert.assertTrue("SDK < 32 apps should have POST_NOTIFICATIONS added implicitly",
+ context.packageManager.getPackageInfo(APP_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS).requestedPermissions!!
+ .contains(POST_NOTIFICATIONS))
+ }
+ }
+
+ @Test
+ fun notificationPermissionIsNotImplicitlyAddedTo33Apps() {
+ installPackage(APP_APK_PATH_LATEST_NONE, expectSuccess = true)
+ runWithShellPermissionIdentity {
+ val requestedPerms = context.packageManager.getPackageInfo(APP_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS).requestedPermissions
+ Assert.assertTrue("SDK >= 33 apps should NOT have POST_NOTIFICATIONS added implicitly",
+ requestedPerms == null || !requestedPerms.contains(POST_NOTIFICATIONS))
+ }
+ }
+
+ @Test
+ fun notificationPromptShowsForLegacyAppAfterCreatingNotificationChannels() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp()
+ clickPermissionRequestAllowButton()
+ }
+
+ @Test
+ fun notificationPromptShowsForLegacyAppWithNotificationChannelsOnStart() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ // create channels, then leave the app
+ launchApp()
+ killTestApp()
+ launchApp()
+ waitFindObject(By.textContains(ALLOW))
+ clickPermissionRequestAllowButton()
+ }
+
+ @Test
+ fun notificationPromptDoesNotShowForLegacyAppWithNoNotificationChannels_onLaunch() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(createChannels = false)
+ assertDialogNotShowing()
+ }
+ @Test
+ fun notificationPromptDoesNotShowForNonLauncherIntentCategoryLaunches_onChannelCreate() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(launcherCategory = false)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptDoesNotShowForNonLauncherIntentCategoryLaunches_onLaunch() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ // create channels, then leave the app
+ launchApp()
+ killTestApp()
+ launchApp(launcherCategory = false)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptDoesNotShowForNonMainIntentActionLaunches_onLaunch() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ // create channels, then leave the app
+ launchApp()
+ killTestApp()
+ launchApp(intentAction = INTENT_ACTION)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptDoesNotShowForNonMainIntentActionLaunches_onChannelCreate() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(intentAction = INTENT_ACTION)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptShowsIfActivityOptionSet() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ // create channels, then leave the app
+ launchApp()
+ killTestApp()
+ launchApp(intentAction = INTENT_ACTION, isEligibleForPromptOption = true)
+ clickPermissionRequestAllowButton()
+ }
+
+ @Test
+ fun notificationPromptShownForSubsequentStartsIfTaskStartWasLauncher() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(startSecondActivity = true)
+ if (isAutomotive || isWatch) {
+ waitFindObject(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+ } else {
+ waitFindObject(By.res(ALLOW_BUTTON))
+ }
+ pressBack()
+ clickPermissionRequestAllowButton()
+ }
+
+ @Test
+ fun notificationPromptNotShownForSubsequentStartsIfTaskStartWasNotLauncher() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(intentAction = INTENT_ACTION, startSecondActivity = true)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptShownForChannelCreateInSecondActivityIfTaskStartWasLauncher() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(startSecondActivity = true, createChannels = false)
+ clickPermissionRequestAllowButton()
+ }
+
+ @Test
+ fun notificationPromptNotShownForChannelCreateInSecondActivityIfTaskStartWasntLauncher() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(intentAction = INTENT_ACTION, startSecondActivity = true, createChannels = false)
+ assertDialogNotShowing()
+ }
+
+ @Test
+ fun notificationPromptNotShownForSubsequentStartsIfSubsequentIsDifferentPkg() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ installPackage(APP_APK_PATH_OTHER_APP, expectSuccess = true)
+ // perform a launcher start, then start a secondary app
+ launchApp(startSecondaryAppAndCreateChannelsAfterSecondStart = true)
+ try {
+ // Watch does not have app bar
+ if (!isWatch) {
+ waitFindObject(By.textContains(SECOND_ACTIVITY_LABEL))
+ }
+ assertDialogNotShowing()
+ } finally {
+ uninstallPackage(OTHER_APP_PACKAGE_NAME)
+ }
+ }
+
+ @Test
+ fun notificationGrantedOnLegacyGrant() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp()
+ clickPermissionRequestAllowButton()
+ assertAppPermissionGrantedState(POST_NOTIFICATIONS, granted = true)
+ }
+
+ @Test
+ fun nonSystemServerPackageCannotShowPromptForOtherPackage() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ runWithShellPermissionIdentity {
+ val grantPermission = Intent(PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER)
+ grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ grantPermission.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES,
+ arrayOf(POST_NOTIFICATIONS))
+ grantPermission.setPackage(context.packageManager.permissionControllerPackageName)
+ grantPermission.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(grantPermission)
+ }
+ try {
+ clickPermissionRequestAllowButton(timeoutMillis = EXPECTED_TIMEOUT_MS)
+ Assert.fail("Expected not to find permission request dialog")
+ } catch (expected: RuntimeException) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ fun mergeAppPermissionRequestIntoNotificationAndVerifyResult() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp()
+ findPermissionRequestAllowButton()
+ // Notification dialog is showing, trigger RECORD_AUDIO check, and wait until it has been
+ // requested
+ val intent = createIntent(requestPermissions = true, intentAction = BROADCAST_ACTION)
+ context.sendBroadcast(intent)
+ countDown.await()
+ Thread.sleep(1000)
+ // reset countDownLatch
+ countDown = CountDownLatch(1)
+
+ clickPermissionRequestAllowButton()
+ assertAppPermissionGrantedState(POST_NOTIFICATIONS, granted = true)
+ clickPermissionRequestAllowForegroundButton()
+ assertAppPermissionGrantedState(RECORD_AUDIO, granted = true)
+ countDown.await()
+ // Result should contain only the microphone request
+ Assert.assertEquals(listOf(RECORD_AUDIO), allowedGroups)
+ }
+
+ @Test
+ fun mergeNotificationRequestIntoAppPermissionRequestAndVerifyResult() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(createChannels = false, requestPermissions = true)
+ findPermissionRequestAllowForegroundButton()
+ // Microphone dialog is showing, trigger Notification check, and wait until it has been
+ // requested
+ val intent = createIntent(createChannels = true, intentAction = BROADCAST_ACTION)
+ context.sendBroadcast(intent)
+ countDown.await()
+ Thread.sleep(1000)
+ // reset countDownLatch
+ countDown = CountDownLatch(1)
+
+ clickPermissionRequestAllowForegroundButton()
+ assertAppPermissionGrantedState(RECORD_AUDIO, granted = true)
+ clickPermissionRequestAllowButton()
+ assertAppPermissionGrantedState(POST_NOTIFICATIONS, granted = true)
+ countDown.await()
+ // Result should contain only the microphone request
+ Assert.assertEquals(listOf(RECORD_AUDIO), allowedGroups)
+ }
+
+ @Test
+ fun legacyAppCannotExplicitlyRequestNotifications() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(createChannels = false, requestNotificationPermission = true)
+ try {
+ clickPermissionRequestAllowButton(timeoutMillis = EXPECTED_TIMEOUT_MS)
+ Assert.fail("Expected not to find permission request dialog")
+ } catch (expected: RuntimeException) {
+ // Do nothing
+ }
+ }
+
+ private fun assertAppPermissionGrantedState(permission: String, granted: Boolean) {
+ SystemUtil.eventually {
+ runWithShellPermissionIdentity {
+ Assert.assertEquals(
+ "Expected $permission to be granted",
+ context.packageManager.checkPermission(permission, APP_PACKAGE_NAME),
+ PERMISSION_GRANTED
+ )
+ }
+ }
+ }
+
+ private fun createIntent(
+ createChannels: Boolean = true,
+ requestNotificationPermission: Boolean = false,
+ requestPermissions: Boolean = false,
+ launcherCategory: Boolean = true,
+ intentAction: String = Intent.ACTION_MAIN,
+ startSecondActivity: Boolean = false,
+ startSecondaryAppAndCreateChannelsAfterSecondStart: Boolean = false
+ ): Intent {
+ val intent =
+ if (intentAction == Intent.ACTION_MAIN && launcherCategory) {
+ packageManager.getLaunchIntentForPackage(APP_PACKAGE_NAME)!!
+ } else {
+ Intent(intentAction)
+ }
+
+ intent.`package` = APP_PACKAGE_NAME
+ intent.putExtra(EXTRA_CREATE_CHANNELS, createChannels)
+ intent.putExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, requestPermissions)
+ intent.putExtra(EXTRA_REQUEST_NOTIF_PERMISSION, requestNotificationPermission)
+ intent.putExtra(EXTRA_START_SECOND_ACTIVITY, startSecondActivity)
+ intent.putExtra(EXTRA_START_SECOND_APP, startSecondaryAppAndCreateChannelsAfterSecondStart)
+ intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ return intent
+ }
+
+ private fun launchApp(
+ createChannels: Boolean = true,
+ requestNotificationPermission: Boolean = false,
+ requestPermissions: Boolean = false,
+ launcherCategory: Boolean = true,
+ intentAction: String = Intent.ACTION_MAIN,
+ isEligibleForPromptOption: Boolean = false,
+ startSecondActivity: Boolean = false,
+ startSecondaryAppAndCreateChannelsAfterSecondStart: Boolean = false
+ ) {
+ val intent =
+ createIntent(
+ createChannels,
+ requestNotificationPermission,
+ requestPermissions,
+ launcherCategory,
+ intentAction,
+ startSecondActivity,
+ startSecondaryAppAndCreateChannelsAfterSecondStart
+ )
+
+ val options = ActivityOptions.makeBasic()
+ options.isEligibleForLegacyPermissionPrompt = isEligibleForPromptOption
+ doAndWaitForWindowTransition {
+ context.startActivity(intent, options.toBundle())
+ }
+
+ // Watch does not have app bar
+ if (!isWatch) {
+ waitFindObject(By.textContains(ACTIVITY_LABEL))
+ }
+ }
+
+ private fun assertDialogNotShowing(timeoutMillis: Long = EXPECTED_TIMEOUT_MS) {
+ try {
+ clickPermissionRequestAllowButton(timeoutMillis)
+ Assert.fail("Expected not to find permission request dialog")
+ } catch (expected: RuntimeException) {
+ // Do nothing
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt
new file mode 100644
index 000000000..495648b55
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionDecisionsTest.kt
@@ -0,0 +1,131 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest
+import android.content.Intent
+import android.os.Build
+import android.permission.PermissionManager
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assert.assertNull
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+@FlakyTest
+class PermissionDecisionsTest : BaseUsePermissionTest() {
+
+ companion object {
+ const val ASSERT_ABSENT_SELECTOR_TIMEOUT_MS = 500L
+ }
+
+ // Permission decisions has only been implemented on Auto
+ @Before
+ fun assumeAuto() {
+ assumeTrue(isAutomotive)
+ }
+
+ @Test
+ fun testAcceptPermissionDialogShowsDecisionWithGrantedAccess() {
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ requestAppPermissionsAndAssertResult(Manifest.permission.ACCESS_FINE_LOCATION to true) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ openPermissionDecisions()
+ waitFindObject(
+ By.hasChild(By.text("You gave $APP_PACKAGE_NAME access to location"))
+ .hasChild(By.text("Today"))
+ )
+ }
+
+ @Test
+ fun testDenyPermissionDialogShowsDecisionWithDeniedAccess() {
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ requestAppPermissionsAndAssertResult(Manifest.permission.ACCESS_FINE_LOCATION to false) {
+ clickPermissionRequestDenyButton()
+ }
+
+ openPermissionDecisions()
+ waitFindObject(
+ By.hasChild(By.text("You denied $APP_PACKAGE_NAME access to location"))
+ .hasChild(By.text("Today"))
+ )
+ }
+
+ @Test
+ fun testAppUninstallRemovesDecision() {
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ requestAppPermissionsAndAssertResult(Manifest.permission.ACCESS_FINE_LOCATION to false) {
+ clickPermissionRequestDenyButton()
+ }
+ uninstallApp()
+
+ openPermissionDecisions()
+ assertNull(
+ waitFindObjectOrNull(
+ By.hasChild(By.text("You denied $APP_PACKAGE_NAME access to location"))
+ .hasChild(By.text("Today")),
+ ASSERT_ABSENT_SELECTOR_TIMEOUT_MS
+ )
+ )
+ }
+
+ @Test
+ fun testClickOnDecisionAndChangeAccessUpdatesDecision() {
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ requestAppPermissionsAndAssertResult(Manifest.permission.ACCESS_FINE_LOCATION to true) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ openPermissionDecisions()
+
+ waitFindObject(
+ By.hasChild(By.text("You gave $APP_PACKAGE_NAME access to location"))
+ .hasChild(By.text("Today"))
+ )
+ .click()
+
+ waitFindObject(By.text(APP_PACKAGE_NAME))
+ waitFindObject(By.text("Location access for this app"))
+
+ // change the permission on the app permission screen and verify that updates the decision
+ // page
+ waitFindObject(By.text("Don’t allow")).click()
+ pressBack()
+ waitFindObject(
+ By.hasChild(By.text("You denied $APP_PACKAGE_NAME access to location"))
+ .hasChild(By.text("Today"))
+ )
+ }
+
+ private fun openPermissionDecisions() {
+ doAndWaitForWindowTransition {
+ SystemUtil.runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(PermissionManager.ACTION_REVIEW_PERMISSION_DECISIONS).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
+ }
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionGroupTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionGroupTest.kt
new file mode 100644
index 000000000..298c35cca
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionGroupTest.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 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.permissionui.cts
+
+import androidx.test.filters.FlakyTest
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for permission groups.
+ */
+@FlakyTest
+class PermissionGroupTest : BaseUsePermissionTest() {
+ @Test
+ fun testRuntimeGroupGrantExpansion23() {
+ installPackage(APP_APK_PATH_23)
+ testRuntimeGroupGrantExpansion(true)
+ }
+
+ @Test
+ fun testRuntimeGroupGrantExpansion25() {
+ installPackage(APP_APK_PATH_25)
+ testRuntimeGroupGrantExpansion(true)
+ }
+
+ @Test
+ fun testRuntimeGroupGrantExpansion26() {
+ installPackage(APP_APK_PATH_26)
+ testRuntimeGroupGrantExpansion(false)
+ }
+
+ @Test
+ fun testRuntimeGroupGrantExpansion30() {
+ installPackage(APP_APK_PATH_30)
+ testRuntimeGroupGrantExpansion(false)
+ }
+
+ @Test
+ fun testPartiallyGrantedGroupExpansion() {
+ installPackage(APP_APK_PATH_30)
+
+ // Start out without permission
+ assertAppHasPermission(android.Manifest.permission.RECEIVE_SMS, false)
+ assertAppHasPermission(android.Manifest.permission.SEND_SMS, false)
+
+ // Grant only RECEIVE_SMS
+ uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME,
+ android.Manifest.permission.RECEIVE_SMS)
+ assertAppHasPermission(android.Manifest.permission.RECEIVE_SMS, true)
+
+ // Request both permissions, and expect that SEND_SMS is granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.RECEIVE_SMS to true,
+ android.Manifest.permission.SEND_SMS to true,
+ waitForWindowTransition = false
+ ) { }
+
+ assertAppHasPermission(android.Manifest.permission.SEND_SMS, true)
+ }
+
+ private fun testRuntimeGroupGrantExpansion(expectExpansion: Boolean) {
+ // Start out without permission
+ assertAppHasPermission(android.Manifest.permission.RECEIVE_SMS, false)
+ assertAppHasPermission(android.Manifest.permission.SEND_SMS, false)
+
+ // Request only one permission from the 'SMS' permission group at runtime,
+ // but two from this group are <uses-permission> in the manifest
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.RECEIVE_SMS to true,
+ waitForWindowTransition = !isWatch
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+
+ assertAppHasPermission(android.Manifest.permission.SEND_SMS, expectExpansion)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionNoOpGtsTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionNoOpGtsTest.kt
new file mode 100644
index 000000000..d36b272ce
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionNoOpGtsTest.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.permissionui.cts
+
+import com.android.compatibility.common.util.CtsDownstreamingTest
+import org.junit.Test
+
+// NoOp test class so that at least one GTS test passes on all platforms.
+// b/235606392 for reference. Will be removed once we move all downstreaming
+// CtsPermissionUiTestCases to GTS.
+@CtsDownstreamingTest
+class PermissionNoOpGtsTest {
+
+ @Test
+ fun shouldAlwaysPass() {}
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionPolicyTest25.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionPolicyTest25.kt
new file mode 100644
index 000000000..f128e804a
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionPolicyTest25.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.permissionui.cts
+
+import android.app.Activity
+import android.content.ComponentName
+import android.content.Intent
+import androidx.test.filters.FlakyTest
+import java.util.concurrent.TimeUnit
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests for the platform permission policy around apps targeting API 25.
+ */
+@FlakyTest
+class PermissionPolicyTest25 : BasePermissionTest() {
+ companion object {
+ const val APP_APK_PATH_25 = "$APK_DIRECTORY/CtsPermissionPolicyApp25.apk"
+ const val APP_PACKAGE_NAME = "android.permissionui.cts.permissionpolicy"
+ }
+
+ @Before
+ fun installApp25() {
+ uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
+ installPackage(APP_APK_PATH_25)
+ }
+
+ @After
+ fun uninstallApp() {
+ uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
+ }
+
+ @Test
+ fun testNoProtectionFlagsAddedToNonSignatureProtectionPermissions() {
+ val future = startActivityForFuture(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.TestProtectionFlagsActivity"
+ )
+ }
+ )
+ val result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ assertEquals(Activity.RESULT_OK, result.resultCode)
+ assertEquals("", result.resultData!!.getStringExtra("$APP_PACKAGE_NAME.ERROR_MESSAGE"))
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
new file mode 100644
index 000000000..43bb05255
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
@@ -0,0 +1,285 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.CAMERA
+import android.os.Build
+import android.provider.DeviceConfig
+import android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.modules.utils.build.SdkLevel
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+
+/**
+ * Permission rationale in Grant Permission Dialog tests. Permission rationale is only available on
+ * U+
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
+
+ @get:Rule
+ val deviceConfigPermissionRationaleEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PERMISSION_RATIONALE_ENABLED,
+ true.toString())
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue("Permission rationale is only available on U+", SdkLevel.isAtLeastU())
+ Assume.assumeFalse(isAutomotive)
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+ }
+
+ @Test
+ fun requestLocationPerm_flagDisabled_noPermissionRationale() {
+ setDeviceConfigPrivacyProperty(PERMISSION_RATIONALE_ENABLED, false.toString())
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_apkHasNoInstallSource_noPermissionRationale() {
+ installPackageWithoutInstallSource(APP_APK_PATH_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_noAppMetadata_noPermissionRationale() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_nullAppMetadata_noPermissionRationale() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_emptyAppMetadata_noPermissionRationale() {
+ installPackageWithInstallSourceAndEmptyMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_invalidAppMetadata_noPermissionRationale() {
+ installPackageWithInstallSourceAndInvalidMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_invalidAppMetadataWithoutTopLevelVersion_noPermissionRationale() {
+ installPackageWithInstallSourceAndMetadataWithoutTopLevelVersion(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_invalidAppMetadataWithInvalidTopLevelVersion_noPermissionRationale() {
+ installPackageWithInstallSourceAndMetadataWithInvalidTopLevelVersion(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_invalidAppMetadataWithoutSafetyLabelVersion_noPermissionRationale() {
+ installPackageWithInstallSourceAndMetadataWithoutSafetyLabelVersion(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_invalidAppMetadataWithInvalidSafetyLabelVersion_noPermissionRationale()
+ {
+ installPackageWithInstallSourceAndMetadataWithInvalidSafetyLabelVersion(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestCameraPerm_noPermissionRationale() {
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(CAMERA, false)
+
+ requestAppPermissionsForNoResult(CAMERA) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestCoarseLocationPerm_hasPermissionRationale_packageSourceUnspecified() {
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(true)
+ }
+ }
+
+ @Test
+ fun requestCoarseLocationPerm_hasPermissionRationale_packageSourceStore() {
+ installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(true)
+ }
+ }
+
+ @Test
+ fun requestCoarseLocationPerm_hasPermissionRationale_packageSourceLocalFile() {
+ installPackageWithInstallSourceAndMetadataFromLocalFile(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestCoarseLocationPerm_hasPermissionRationale_packageSourceDownloadedFile() {
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestCoarseLocationPerm_hasPermissionRationale_packageSourceOther() {
+ installPackageWithInstallSourceAndMetadataFromOther(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestFineLocationPerm_hasPermissionRationale() {
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(true)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_clicksPermissionRationale_startsPermissionRationaleActivity() {
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {
+ clickPermissionRationaleViewInGrantDialog()
+ assertPermissionRationaleDialogIsVisible(true)
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ @Test
+ fun requestLocationPerm_clicksPermissionRationale_startsPermissionRationaleActivity_comesBack(
+ ) {
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {
+ clickPermissionRationaleViewInGrantDialog()
+ assertPermissionRationaleDialogIsVisible(true)
+ pressBack()
+ assertPermissionRationaleDialogIsVisible(false)
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(true)
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationaleTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationaleTest.kt
new file mode 100644
index 000000000..fd3d0be29
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationaleTest.kt
@@ -0,0 +1,398 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest
+import android.app.ActivityManager
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.provider.DeviceConfig
+import android.safetylabel.SafetyLabelConstants.PERMISSION_RATIONALE_ENABLED
+import android.text.Spanned
+import android.text.style.ClickableSpan
+import android.util.Log
+import android.view.View
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.modules.utils.build.SdkLevel
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+/** Permission rationale activity tests. Permission rationale is only available on U+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class PermissionRationaleTest : BaseUsePermissionTest() {
+
+ private var activityManager: ActivityManager? = null
+
+ @get:Rule
+ val deviceConfigPermissionRationaleEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PERMISSION_RATIONALE_ENABLED,
+ true.toString())
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue("Permission rationale is only available on U+", SdkLevel.isAtLeastU())
+ Assume.assumeFalse(isAutomotive)
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+
+ activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
+
+ enableComponent(TEST_INSTALLER_ACTIVITY_COMPONENT_NAME)
+
+ installPackageWithInstallSourceAndMetadata(APP_APK_NAME_31)
+
+ assertAppHasPermission(Manifest.permission.ACCESS_FINE_LOCATION, false)
+ }
+
+ @After
+ fun disableTestInstallerActivity() {
+ disableComponent(TEST_INSTALLER_ACTIVITY_COMPONENT_NAME)
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByNullMetadata() {
+ installPackageWithInstallSourceAndNoMetadata(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByEmptyMetadata() {
+ installPackageWithInstallSourceAndEmptyMetadata(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByNoTopLevelVersion() {
+ installPackageWithInstallSourceAndMetadataWithoutTopLevelVersion(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByInvalidTopLevelVersion() {
+ installPackageWithInstallSourceAndMetadataWithInvalidTopLevelVersion(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByNoSafetyLabelVersion() {
+ installPackageWithInstallSourceAndMetadataWithoutSafetyLabelVersion(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity_failedByInvalidSafetyLabelVersion() {
+ installPackageWithInstallSourceAndMetadataWithInvalidSafetyLabelVersion(APP_APK_NAME_31)
+ navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer()
+ }
+
+ @Test
+ fun startsPermissionRationaleActivity() {
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleDialogIsVisible(true)
+ }
+
+ @Test
+ fun linksToInstallSource() {
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleDialogIsVisible(true)
+
+ clickInstallSourceLink()
+
+ eventually {
+ assertStoreLinkClickSuccessful(installerPackageName = TEST_INSTALLER_PACKAGE_NAME)
+ }
+ }
+
+ @Ignore("b/282063206")
+ @Test
+ fun clickLinkToHelpCenter_opensHelpCenter() {
+ Assume.assumeFalse(getPermissionControllerResString(HELP_CENTER_URL_ID).isNullOrEmpty())
+
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleActivityTitleIsVisible(true)
+ assertHelpCenterLinkAvailable(true)
+
+ clickHelpCenterLink()
+
+ eventually({assertHelpCenterLinkClickSuccessful()}, NEW_WINDOW_TIMEOUT_MILLIS)
+ }
+
+ @Test
+ fun noHelpCenterLinkAvailable_noHelpCenterClickAction() {
+ Assume.assumeTrue(getPermissionControllerResString(HELP_CENTER_URL_ID).isNullOrEmpty())
+
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleActivityTitleIsVisible(true)
+ assertHelpCenterLinkAvailable(false)
+ }
+
+ @Test
+ fun linksToSettings_noOp_dialogsNotClosed() {
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleDialogIsVisible(true)
+
+ clicksSettings_doesNothing_leaves()
+
+ eventually {
+ assertPermissionRationaleDialogIsVisible(true)
+ }
+ }
+
+ @Test
+ fun linksToSettings_grants_dialogsClose() {
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleDialogIsVisible(true)
+
+ clicksSettings_allowsForeground_leaves()
+
+ // Setting, Permission rationale and Grant dialog should be dismissed
+ eventually {
+ assertPermissionSettingsVisible(false)
+ assertPermissionRationaleDialogIsVisible(false)
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+
+ assertAppHasPermission(Manifest.permission.ACCESS_FINE_LOCATION, true)
+ }
+
+ @Test
+ fun linksToSettings_denies_dialogsClose() {
+ navigateToPermissionRationaleActivity()
+
+ assertPermissionRationaleDialogIsVisible(true)
+
+ clicksSettings_denies_leaves()
+
+ // Setting, Permission rationale and Grant dialog should be dismissed
+ eventually {
+ assertPermissionSettingsVisible(false)
+ assertPermissionRationaleDialogIsVisible(false)
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+
+ assertAppHasPermission(Manifest.permission.ACCESS_FINE_LOCATION, false)
+ }
+
+ private fun navigateToPermissionRationaleActivity_failedShowPermissionRationaleContainer() {
+ requestAppPermissionsForNoResult(Manifest.permission.ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
+ }
+ }
+
+ private fun navigateToPermissionRationaleActivity() {
+ requestAppPermissionsForNoResult(Manifest.permission.ACCESS_FINE_LOCATION) {
+ assertPermissionRationaleContainerOnGrantDialogIsVisible(true)
+ clickPermissionRationaleViewInGrantDialog()
+ }
+ }
+
+ private fun clickInstallSourceLink() {
+ findView(By.res(DATA_SHARING_SOURCE_MESSAGE_ID), true)
+
+ eventually {
+ // UiObject2 doesn't expose CharSequence.
+ val node = uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ DATA_SHARING_SOURCE_MESSAGE_ID
+ )[0]
+ assertTrue(node.isVisibleToUser)
+ val text = node.text as Spanned
+ val clickableSpan = text.getSpans(0, text.length, ClickableSpan::class.java)[0]
+ // We could pass in null here in Java, but we need an instance in Kotlin.
+ doAndWaitForWindowTransition {
+ clickableSpan.onClick(View(context))
+ }
+ }
+ }
+
+ private fun clickHelpCenterLink() {
+ findView(By.res(LEARN_MORE_MESSAGE_ID), true)
+
+ eventually {
+ // UiObject2 doesn't expose CharSequence.
+ val node = uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ LEARN_MORE_MESSAGE_ID
+ )[0]
+ assertTrue(node.isVisibleToUser)
+ val text = node.text as Spanned
+ val clickableSpan = text.getSpans(0, text.length, ClickableSpan::class.java)[0]
+ // We could pass in null here in Java, but we need an instance in Kotlin.
+ doAndWaitForWindowTransition {
+ clickableSpan.onClick(View(context))
+ }
+ }
+ }
+
+ private fun clickSettingsLink() {
+ findView(By.res(SETTINGS_MESSAGE_ID), true)
+
+ eventually {
+ // UiObject2 doesn't expose CharSequence.
+ val node = uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ SETTINGS_MESSAGE_ID
+ )[0]
+ assertTrue(node.isVisibleToUser)
+ val text = node.text as Spanned
+ val clickableSpan = text.getSpans(0, text.length, ClickableSpan::class.java)[0]
+ // We could pass in null here in Java, but we need an instance in Kotlin.
+ doAndWaitForWindowTransition {
+ clickableSpan.onClick(View(context))
+ }
+ }
+ }
+
+ private fun clicksSettings_doesNothing_leaves() {
+ clickSettingsLink()
+ eventually {
+ assertPermissionSettingsVisible(true)
+ }
+ pressBack()
+ }
+
+ private fun clicksSettings_allowsForeground_leaves() {
+ clickSettingsLink()
+ eventually {
+ clickAllowForegroundInSettings()
+ }
+ pressBack()
+ }
+
+ private fun clicksSettings_denies_leaves() {
+ clickSettingsLink()
+ eventually {
+ clicksDenyInSettings()
+ }
+ pressBack()
+ }
+
+ private fun assertHelpCenterLinkAvailable(expected: Boolean) {
+ // Message should always be visible
+ findView(By.res(LEARN_MORE_MESSAGE_ID), true)
+
+ // Verify the link is (or isn't) in message
+ eventually {
+ // UiObject2 doesn't expose CharSequence.
+ val node = uiAutomation.rootInActiveWindow.findAccessibilityNodeInfosByViewId(
+ LEARN_MORE_MESSAGE_ID
+ )[0]
+ assertTrue(node.isVisibleToUser)
+ val text = node.text as Spanned
+ val clickableSpans = text.getSpans(0, text.length, ClickableSpan::class.java)
+
+ if (expected) {
+ assertFalse("Expected help center link, but none found",
+ clickableSpans.isEmpty())
+ } else {
+ assertTrue("Expected no links, but found one", clickableSpans.isEmpty())
+ }
+ }
+ }
+
+ private fun assertPermissionSettingsVisible(expected: Boolean) {
+ findView(By.res(DENY_RADIO_BUTTON), expected = expected)
+ }
+
+ private fun assertStoreLinkClickSuccessful(
+ installerPackageName: String,
+ packageName: String? = null
+ ) {
+ SystemUtil.runWithShellPermissionIdentity {
+ val runningTasks = activityManager!!.getRunningTasks(1)
+
+ assertFalse("Expected runningTasks to not be empty",
+ runningTasks.isEmpty())
+
+ val taskInfo = runningTasks[0]
+ val observedIntentAction = taskInfo.baseIntent.action
+ val observedPackageName = taskInfo.baseIntent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
+ val observedInstallerPackageName = taskInfo.topActivity?.packageName
+
+ assertEquals("Unexpected intent action",
+ Intent.ACTION_SHOW_APP_INFO,
+ observedIntentAction)
+ assertEquals("Unexpected installer package name",
+ installerPackageName,
+ observedInstallerPackageName)
+ assertEquals("Unexpected package name",
+ packageName,
+ observedPackageName)
+ }
+ }
+
+ private fun assertHelpCenterLinkClickSuccessful() {
+ SystemUtil.runWithShellPermissionIdentity {
+ val runningTasks = activityManager!!.getRunningTasks(5)
+
+ Log.v(TAG, "# running tasks: ${runningTasks.size}")
+ assertFalse("Expected runningTasks to not be empty", runningTasks.isEmpty())
+
+ runningTasks.forEachIndexed { index, runningTaskInfo ->
+ Log.v(TAG, "task $index ${runningTaskInfo.baseIntent}")
+ }
+
+ val taskInfo = runningTasks[0]
+ val observedIntentAction = taskInfo.baseIntent.action
+ val observedIntentDataString = taskInfo.baseIntent.dataString
+ val observedIntentScheme: String? = taskInfo.baseIntent.scheme
+
+ Log.v(TAG, "task base intent: ${taskInfo.baseIntent}")
+ assertEquals("Unexpected intent action", Intent.ACTION_VIEW, observedIntentAction)
+
+ val expectedUrl = getPermissionControllerResString(HELP_CENTER_URL_ID)!!
+ assertFalse(observedIntentDataString.isNullOrEmpty())
+ assertTrue(observedIntentDataString?.startsWith(expectedUrl) ?: false)
+
+ assertFalse(observedIntentScheme.isNullOrEmpty())
+ assertEquals("https", observedIntentScheme)
+ }
+ }
+
+ companion object {
+ private val TAG = PermissionRationaleTest::class.java.simpleName
+
+ private const val DATA_SHARING_SOURCE_MESSAGE_ID =
+ "com.android.permissioncontroller:id/data_sharing_source_message"
+ private const val LEARN_MORE_MESSAGE_ID =
+ "com.android.permissioncontroller:id/learn_more_message"
+ private const val SETTINGS_MESSAGE_ID =
+ "com.android.permissioncontroller:id/settings_message"
+
+ private const val HELP_CENTER_URL_ID = "data_sharing_help_center_link"
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTapjackingTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTapjackingTest.kt
new file mode 100644
index 000000000..cd771f8a2
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTapjackingTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts
+
+import android.content.ComponentName
+import android.content.Intent
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil
+import java.lang.Exception
+import org.junit.After
+import org.junit.Assert
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests permission review screen can't be tapjacked
+ */
+@FlakyTest
+class PermissionReviewTapjackingTest : BaseUsePermissionTest() {
+
+ companion object {
+ const val HELPER_APP_OVERLAY = "$APK_DIRECTORY/CtsHelperAppOverlay.apk"
+ private const val HELPER_PACKAGE_NAME = "android.permissionui.cts.helper.overlay"
+ }
+
+ @Before
+ fun installApp22AndApprovePermissionReview() {
+ assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+
+ installPackage(APP_APK_PATH_22)
+ installPackage(HELPER_APP_OVERLAY)
+
+ SystemUtil.runShellCommandOrThrow(
+ "appops set $HELPER_PACKAGE_NAME android:system_alert_window allow")
+ }
+
+ @After
+ fun uninstallPackages() {
+ SystemUtil.runShellCommandOrThrow(
+ "pm uninstall $APP_PACKAGE_NAME")
+ SystemUtil.runShellCommandOrThrow(
+ "pm uninstall $HELPER_PACKAGE_NAME")
+ }
+
+ @Test
+ fun testOverlaysAreHidden() {
+ context.startActivity(Intent()
+ .setComponent(ComponentName(HELPER_PACKAGE_NAME,
+ "$HELPER_PACKAGE_NAME.OverlayActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
+ findOverlay()
+
+ context.startActivity(Intent()
+ .setComponent(ComponentName(APP_PACKAGE_NAME,
+ "$APP_PACKAGE_NAME.FinishOnCreateActivity"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ )
+
+ if (isWatch) {
+ waitFindObject(
+ By.text(getPermissionControllerString("review_button_cancel")), TIMEOUT_MILLIS * 2
+ )
+ } else {
+ waitFindObject(By.res("com.android.permissioncontroller:id/permissions_message"))
+ }
+
+ try {
+ findOverlay()
+ Assert.fail("Overlay was displayed")
+ } catch (e: Exception) {
+ // expected
+ }
+
+ pressHome()
+ findOverlay()
+ }
+
+ private fun findOverlay() = waitFindObject(By.text("Find me!"))
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTest.kt
new file mode 100644
index 000000000..7c0f69a52
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionReviewTest.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2018 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.permissionui.cts
+
+import android.app.Activity
+import android.content.ComponentName
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.ResultReceiver
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.rule.ActivityTestRule
+import androidx.test.runner.AndroidJUnit4
+import androidx.test.uiautomator.By
+import java.util.concurrent.LinkedBlockingQueue
+import java.util.concurrent.TimeUnit
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@FlakyTest
+class PermissionReviewTest : BaseUsePermissionTest() {
+
+ @Before
+ fun assumeNotIndividuallyControlled() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+ }
+
+ @Before
+ fun installApp22CalendarOnly() {
+ installPackage(APP_APK_PATH_22_CALENDAR_ONLY)
+ }
+
+ @get:Rule
+ val activityRule = ActivityTestRule(StartForFutureActivity::class.java, false, false)
+
+ @Test
+ fun testDenyCalendarDuringReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
+ // Deny
+ clickPermissionControllerUi(By.text("Calendar"))
+ // Confirm deny
+ click(By.res("android:id/button1"))
+
+ clickPermissionReviewContinue()
+ }
+
+ clearTargetSdkWarning()
+ assertAppHasCalendarAccess(false)
+ }
+
+ @Test
+ fun testDenyGrantCalendarDuringReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
+ // Deny
+ clickPermissionControllerUi(By.text("Calendar"))
+ // Confirm deny
+ click(By.res("android:id/button1"))
+
+ // Grant
+ clickPermissionControllerUi(By.text("Calendar"))
+
+ clickPermissionReviewContinue()
+ }
+
+ clearTargetSdkWarning()
+ assertAppHasCalendarAccess(true)
+ }
+
+ @Test
+ fun testDenyGrantDenyCalendarDuringReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_OK) {
+ // Deny
+ clickPermissionControllerUi(By.text("Calendar"))
+
+ // Confirm deny
+ click(By.res("android:id/button1"))
+
+ // Grant
+ clickPermissionControllerUi(By.text("Calendar"))
+
+ // Deny
+ clickPermissionControllerUi(By.text("Calendar"))
+
+ clickPermissionReviewContinue()
+ }
+
+ clearTargetSdkWarning()
+ assertAppHasCalendarAccess(false)
+ }
+
+ @Test
+ fun testCancelReview() {
+ // Start APK_22_ONLY_CALENDAR, but cancel review
+ cancelPermissionReview()
+
+ // Start APK_22_ONLY_CALENDAR again, now approve review
+ approvePermissionReview()
+
+ assertAppDoesNotNeedPermissionReview()
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "TIRAMISU")
+ fun testNotificationPermissionAddedToReview() {
+ startAppActivityAndAssertResultCode(Activity.RESULT_CANCELED) {
+ waitFindObject(By.text("Notifications"), 5000L)
+ clickPermissionReviewCancel()
+ }
+ }
+
+ @Test
+ fun testReviewPermissionWhenServiceIsBound() {
+ val results = LinkedBlockingQueue<Int>()
+ // We are starting a activity instead of the service directly, because
+ // the service comes from a different app than the CTS tests.
+ // This app will be considered idle on devices that have idling enabled (automotive),
+ // and the service wouldn't be allowed to be started without the activity.
+ activityRule.launchActivity(null).startActivity(
+ Intent().apply {
+ component = ComponentName(
+ APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.StartCheckPermissionServiceActivity"
+ )
+ putExtra(
+ "$APP_PACKAGE_NAME.RESULT",
+ object : ResultReceiver(Handler(Looper.getMainLooper())) {
+ override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
+ results.offer(resultCode)
+ }
+ }
+ )
+ putExtra(
+ "$APP_PACKAGE_NAME.PERMISSION", android.Manifest.permission.READ_CALENDAR
+ )
+ }
+ )
+
+ // Service is not started before permission are reviewed
+ assertNull(results.poll(UNEXPECTED_TIMEOUT_MILLIS.toLong(), TimeUnit.MILLISECONDS))
+
+ clickPermissionReviewContinueAndClearSdkWarning()
+
+ // Service should be started after permission review
+ assertEquals(
+ PackageManager.PERMISSION_GRANTED, results.poll(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ )
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt
new file mode 100644
index 000000000..5a6ed45fb
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionSplitTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2018 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.permissionui.cts
+
+import android.os.Build
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for permission splits.
+ */
+@FlakyTest
+class PermissionSplitTest : BaseUsePermissionTest() {
+ @Before
+ fun assumeNotTv() {
+ assumeFalse(isTv)
+ }
+
+ @Test
+ fun testPermissionSplit28() {
+ installPackage(APP_APK_PATH_28)
+ testLocationPermissionSplit(true)
+ }
+
+ @Test
+ fun testPermissionNotSplit29() {
+ installPackage(APP_APK_PATH_29)
+ testLocationPermissionSplit(false)
+ }
+
+ @Test
+ fun testPermissionNotSplit30() {
+ installPackage(APP_APK_PATH_30)
+ testLocationPermissionSplit(false)
+ }
+
+ @Test
+ fun testPermissionNotSplitLatest() {
+ installPackage(APP_APK_PATH_LATEST)
+ testLocationPermissionSplit(false)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @Test
+ fun testBodySensorSplit() {
+ installPackage(APP_APK_PATH_31)
+ testBodySensorPermissionSplit(true)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @Test
+ fun testBodySensorSplit32() {
+ installPackage(APP_APK_PATH_32)
+ testBodySensorPermissionSplit(true)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ @Test
+ fun testBodySensorNonSplit() {
+ installPackage(APP_APK_PATH_LATEST)
+ testBodySensorPermissionSplit(false)
+ }
+
+ private fun testLocationPermissionSplit(expectSplit: Boolean) {
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ waitForWindowTransition = false
+ ) {
+ if (expectSplit) {
+ clickPermissionRequestSettingsLinkAndAllowAlways()
+ } else {
+ doAndWaitForWindowTransition {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+ }
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, expectSplit)
+ }
+
+ private fun testBodySensorPermissionSplit(expectSplit: Boolean) {
+ assertAppHasPermission(android.Manifest.permission.BODY_SENSORS, false)
+ assertAppHasPermission(android.Manifest.permission.BODY_SENSORS_BACKGROUND, false)
+
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.BODY_SENSORS to true,
+ waitForWindowTransition = false
+ ) {
+ if (expectSplit) {
+ clickPermissionRequestSettingsLinkAndAllowAlways()
+ } else {
+ doAndWaitForWindowTransition {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+ }
+
+ assertAppHasPermission(android.Manifest.permission.BODY_SENSORS_BACKGROUND, expectSplit)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTapjackingTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTapjackingTest.kt
new file mode 100644
index 000000000..8a855f9a0
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTapjackingTest.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Point
+import android.os.Build
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests permissions can't be tapjacked
+ */
+@FlakyTest
+class PermissionTapjackingTest : BaseUsePermissionTest() {
+
+ @Before
+ fun installAppLatest() {
+ installPackage(APP_APK_PATH_WITH_OVERLAY)
+ }
+
+ @Test
+ fun testTapjackGrantDialog_fullOverlay() {
+ // PermissionController for television uses a floating window.
+ assumeFalse(isTv)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
+
+ val buttonCenter = waitFindObject(By.text(
+ getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT))).visibleCenter
+
+ // Wait for overlay to hide the dialog
+ context.sendBroadcast(Intent(ACTION_SHOW_OVERLAY)
+ .putExtra(EXTRA_FULL_OVERLAY, true))
+ waitFindObject(By.res("android.permissionui.cts.usepermission:id/overlay"))
+
+ tryClicking(buttonCenter)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+ @Test
+ fun testTapjackGrantDialog_partialOverlay() {
+ // PermissionController for television uses a floating window.
+ assumeFalse(isTv)
+
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {}
+
+ val foregroundButtonCenter = waitFindObject(By.text(
+ getPermissionControllerString(ALLOW_FOREGROUND_BUTTON_TEXT))).visibleCenter
+ val oneTimeButton = waitFindObjectOrNull(By.text(
+ getPermissionControllerString(ALLOW_ONE_TIME_BUTTON_TEXT)))
+ // If one-time button is not available, fallback to deny button
+ val overlayButtonBounds = oneTimeButton?.visibleBounds
+ ?: waitFindObject(By.text(getPermissionControllerString(
+ DENY_BUTTON_TEXT))).visibleBounds
+
+ // Wait for overlay to hide the dialog
+ context.sendBroadcast(Intent(ACTION_SHOW_OVERLAY)
+ .putExtra(EXTRA_FULL_OVERLAY, false)
+ .putExtra(OVERLAY_LEFT, overlayButtonBounds.left)
+ .putExtra(OVERLAY_TOP, overlayButtonBounds.top)
+ .putExtra(OVERLAY_RIGHT, overlayButtonBounds.right)
+ .putExtra(OVERLAY_BOTTOM, overlayButtonBounds.bottom))
+ waitFindObject(By.res("android.permissionui.cts.usepermission:id/overlay"))
+
+ tryClicking(foregroundButtonCenter)
+ }
+
+ private fun tryClicking(buttonCenter: Point) {
+ try {
+ // Try to grant the permission, this should fail
+ SystemUtil.eventually({
+ if (packageManager.checkPermission(ACCESS_FINE_LOCATION, APP_PACKAGE_NAME) ==
+ PackageManager.PERMISSION_DENIED) {
+ uiDevice.click(buttonCenter.x, buttonCenter.y)
+ Thread.sleep(100)
+ }
+ assertAppHasPermission(ACCESS_FINE_LOCATION, true)
+ }, 10000)
+ } catch (e: RuntimeException) {
+ // expected
+ }
+ // Permission should not be granted
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+
+ // Verify that clicking the dialog without the overlay still works
+ context.sendBroadcast(Intent(ACTION_HIDE_OVERLAY))
+ SystemUtil.eventually({
+ if (packageManager.checkPermission(ACCESS_FINE_LOCATION, APP_PACKAGE_NAME) ==
+ PackageManager.PERMISSION_DENIED) {
+ uiDevice.click(buttonCenter.x, buttonCenter.y)
+ Thread.sleep(100)
+ }
+ assertAppHasPermission(ACCESS_FINE_LOCATION, true)
+ }, 10000)
+ }
+
+ companion object {
+ const val ACTION_SHOW_OVERLAY = "android.permissionui.cts.usepermission.ACTION_SHOW_OVERLAY"
+ const val ACTION_HIDE_OVERLAY = "android.permissionui.cts.usepermission.ACTION_HIDE_OVERLAY"
+
+ const val EXTRA_FULL_OVERLAY = "android.permissionui.cts.usepermission.extra.FULL_OVERLAY"
+
+ const val OVERLAY_LEFT = "android.permissionui.cts.usepermission.extra.OVERLAY_LEFT"
+ const val OVERLAY_TOP = "android.permissionui.cts.usepermission.extra.OVERLAY_TOP"
+ const val OVERLAY_RIGHT = "android.permissionui.cts.usepermission.extra.OVERLAY_RIGHT"
+ const val OVERLAY_BOTTOM = "android.permissionui.cts.usepermission.extra.OVERLAY_BOTTOM"
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest22.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest22.kt
new file mode 100755
index 000000000..b529463de
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest22.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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.permissionui.cts
+
+import androidx.test.filters.FlakyTest
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for apps targeting API 22.
+ */
+@FlakyTest
+class PermissionTest22 : BaseUsePermissionTest() {
+
+ @Before
+ fun installApp22AndApprovePermissionReview() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+
+ installPackage(APP_APK_PATH_22)
+ approvePermissionReview()
+ }
+
+ @Test
+ fun testCompatDefault() {
+ // Legacy permission model appears granted
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
+ assertAppHasCalendarAccess(true)
+ }
+
+ @Test
+ fun testCompatRevoked() {
+ // Revoke the permission
+ revokeAppPermissionsByUi(android.Manifest.permission.WRITE_CALENDAR, isLegacyApp = true)
+
+ // Legacy permission model appears granted
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
+ // Read/write access should be ignored
+ assertAppHasCalendarAccess(false)
+ }
+
+ @Test
+ fun testNoRuntimePrompt() {
+ // Request the permission and do nothing
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ arrayOf(android.Manifest.permission.SEND_SMS), emptyArray(),
+ waitForWindowTransition = false
+ ) {}
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt
new file mode 100644
index 000000000..65093a402
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2015 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.permissionui.cts
+
+import android.content.pm.PackageManager
+import android.permission.cts.MtsIgnore
+import androidx.test.filters.FlakyTest
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assert
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for apps targeting API 23.
+ */
+@FlakyTest
+class PermissionTest23 : BaseUsePermissionTest() {
+ companion object {
+ private const val NON_EXISTENT_PERMISSION = "permission.does.not.exist"
+ private const val INVALID_PERMISSION = "$APP_PACKAGE_NAME.abadname"
+ }
+
+ @Before
+ fun installApp23() {
+ installPackage(APP_APK_PATH_23)
+ }
+
+ @Test
+ fun testDefault() {
+ // New permission model is denied by default
+ assertAppHasAllOrNoPermissions(false)
+ }
+
+ @Test
+ fun testGranted() {
+ grantAppPermissionsByUi(android.Manifest.permission.READ_CALENDAR)
+
+ // Read/write access should be allowed
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
+ assertAppHasCalendarAccess(true)
+ }
+
+ @Test
+ fun testInteractiveGrant() {
+ // Start out without permission
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
+ assertAppHasCalendarAccess(false)
+
+ // Go through normal grant flow
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.READ_CALENDAR to true,
+ android.Manifest.permission.WRITE_CALENDAR to true
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+
+ // We should have permission now!
+ assertAppHasCalendarAccess(true)
+ }
+
+ @Test
+ fun testRuntimeGroupGrantSpecificity() {
+ // Start out without permission
+ assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+
+ // Request only one permission from the 'contacts' permission group
+ // Expect the permission is granted
+ requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to true) {
+ clickPermissionRequestAllowButton()
+ }
+
+ // Make sure no undeclared as used permissions are granted
+ assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
+ }
+
+ @Test
+ fun testCancelledPermissionRequest() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+
+ // Request the permission and cancel the request
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to false) {
+ clickPermissionRequestDenyButton()
+ }
+ }
+
+ @Test
+ fun testRequestGrantedPermission() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+
+ // Request the permission and allow it
+ // Expect the permission is granted
+ requestAppPermissionsAndAssertResult(android.Manifest.permission.WRITE_CONTACTS to true) {
+ clickPermissionRequestAllowButton()
+ }
+
+ // Request the permission and do nothing
+ // Expect the permission is granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.WRITE_CONTACTS to true,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testDenialWithPrejudice() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+
+ // Request the permission and deny it twice
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.WRITE_CONTACTS to false,
+ askTwice = true
+ ) {
+ clickPermissionRequestDenyButton()
+ denyPermissionRequestWithPrejudice()
+ }
+
+ // Request the permission and do nothing
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.WRITE_CONTACTS to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @FlakyTest
+ @MtsIgnore
+ @Test
+ fun testRevokeAffectsWholeGroup() {
+ // Grant the group
+ grantAppPermissionsByUi(android.Manifest.permission.READ_CALENDAR)
+
+ // Make sure we have the permissions
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, true)
+
+ // Revoke the group
+ revokeAppPermissionsByUi(android.Manifest.permission.READ_CALENDAR)
+
+ // Make sure we don't have the permissions
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
+ }
+
+ @Test
+ fun testGrantPreviouslyRevokedWithPrejudiceShowsPrompt() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+
+ // Request the permission and deny it twice
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.READ_CALENDAR to false,
+ askTwice = true
+ ) {
+ clickPermissionRequestDenyButton()
+ denyPermissionRequestWithPrejudice()
+ }
+
+ // Clear the denial with prejudice
+ uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME,
+ android.Manifest.permission.READ_CALENDAR)
+ revokeAppPermissionsByUi(android.Manifest.permission.READ_CALENDAR)
+
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+
+ // Request the permission and allow it
+ // Make sure the permission is granted
+ requestAppPermissionsAndAssertResult(android.Manifest.permission.READ_CALENDAR to true) {
+ clickPermissionRequestAllowButton()
+ }
+ }
+
+ @Test
+ fun testRequestNonRuntimePermission() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.BIND_PRINT_SERVICE, false)
+
+ // Request the permission and do nothing
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.BIND_PRINT_SERVICE to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testRequestNonExistentPermission() {
+ // Make sure we don't have the permission
+ assertAppHasPermission(NON_EXISTENT_PERMISSION, false)
+
+ // Request the permission and do nothing
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ NON_EXISTENT_PERMISSION to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testRequestPermissionFromTwoGroups() {
+ // Make sure we don't have the permissions
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+
+ // Request the permission and allow it
+ // Expect the permission are granted
+ val result = requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.WRITE_CONTACTS to true,
+ android.Manifest.permission.WRITE_CALENDAR to true
+ ) {
+ clickPermissionRequestAllowButton()
+ clickPermissionRequestAllowButton()
+ }
+
+ // In API < N_MR1 all permissions of a group are granted. I.e. the grant was "expanded"
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ // Even the contacts group was expanded, the read-calendar permission is not in the
+ // manifest, hence not granted.
+ assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
+ }
+
+ @Test(timeout = 180000)
+ @FlakyTest
+ @MtsIgnore
+ fun testNoResidualPermissionsOnUninstall() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+
+ // Grant one permission via UI, and the rest via automation
+ grantAppPermissionsByUi(android.Manifest.permission.WRITE_CALENDAR)
+ grantRuntimePermissions(android.Manifest.permission.WRITE_CONTACTS,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.CALL_PHONE,
+ android.Manifest.permission.RECORD_AUDIO,
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.BODY_SENSORS,
+ )
+ uninstallPackage(APP_PACKAGE_NAME)
+ installPackage(APP_APK_PATH_23)
+
+ // Make no permissions are granted after uninstalling and installing the app
+ assertAppHasAllOrNoPermissions(false)
+ }
+
+ @Test
+ fun testNullPermissionRequest() {
+ val permissions: Array<String?> = arrayOf(null)
+ val results: Array<Pair<String?, Boolean>> = arrayOf()
+ // Go through normal grant flow
+ requestAppPermissionsAndAssertResult(
+ permissions,
+ results,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testNullAndRealPermission() {
+ // Make sure we don't have the permissions
+ assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
+ assertAppHasPermission(android.Manifest.permission.RECORD_AUDIO, false)
+
+ // Request the permission and allow it
+ // Expect the permission are granted
+ requestAppPermissionsAndAssertResult(
+ arrayOf(
+ android.Manifest.permission.WRITE_CONTACTS,
+ null,
+ android.Manifest.permission.RECORD_AUDIO,
+ null),
+ arrayOf(
+ android.Manifest.permission.WRITE_CONTACTS to true,
+ android.Manifest.permission.RECORD_AUDIO to true)
+ ) {
+ clickPermissionRequestAllowForegroundButton()
+ clickPermissionRequestAllowButton()
+ }
+ }
+
+ @Test
+ fun testInvalidPermission() {
+ // Request the permission and allow it
+ // Expect the permission is not granted
+ requestAppPermissionsAndAssertResult(
+ INVALID_PERMISSION to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testAskButtonSetsFlags() {
+ Assume.assumeFalse("other form factors might not support the ask button",
+ isTv || isAutomotive || isWatch)
+
+ grantAppPermissionsByUi(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, true)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, true)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, true)
+
+ revokeAppPermissionsByUi(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION)
+ SystemUtil.runWithShellPermissionIdentity {
+ val perms = listOf(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ for (perm in perms) {
+ var flags = packageManager.getPermissionFlags(perm, APP_PACKAGE_NAME, context.user)
+ Assert.assertEquals("USER_SET should not be set for $perm", 0,
+ flags and PackageManager.FLAG_PERMISSION_USER_SET)
+ Assert.assertEquals("USER_FIXED should not be set for $perm", 0,
+ flags and PackageManager.FLAG_PERMISSION_USER_FIXED)
+ Assert.assertEquals("ONE_TIME should be set for $perm",
+ PackageManager.FLAG_PERMISSION_ONE_TIME,
+ flags and PackageManager.FLAG_PERMISSION_ONE_TIME)
+ }
+ }
+ }
+
+ private fun denyPermissionRequestWithPrejudice() {
+ if (isTv || isWatch) {
+ clickPermissionRequestDontAskAgainButton()
+ } else {
+ clickPermissionRequestDenyAndDontAskAgainButton()
+ }
+ }
+
+ private fun assertAppHasAllOrNoPermissions(expectPermissions: Boolean) {
+ arrayOf(
+ android.Manifest.permission.SEND_SMS,
+ android.Manifest.permission.RECEIVE_SMS,
+ android.Manifest.permission.RECEIVE_WAP_PUSH,
+ android.Manifest.permission.RECEIVE_MMS,
+ android.Manifest.permission.READ_CALENDAR,
+ android.Manifest.permission.WRITE_CALENDAR,
+ android.Manifest.permission.WRITE_CONTACTS,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_CALL_LOG,
+ android.Manifest.permission.WRITE_CALL_LOG,
+ android.Manifest.permission.ADD_VOICEMAIL,
+ android.Manifest.permission.CALL_PHONE,
+ android.Manifest.permission.USE_SIP,
+ android.Manifest.permission.PROCESS_OUTGOING_CALLS,
+ android.Manifest.permission.RECORD_AUDIO,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.BODY_SENSORS,
+ android.Manifest.permission.READ_CELL_BROADCASTS,
+ // Split permissions
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ // Storage permissions
+ android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ).forEach {
+ assertAppHasPermission(it, expectPermissions)
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest29.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest29.kt
new file mode 100644
index 000000000..09b4092be
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest29.kt
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 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.permissionui.cts
+
+import android.permission.cts.MtsIgnore
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.eventually
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for apps targeting API 29.
+ */
+@FlakyTest
+class PermissionTest29 : BaseUsePermissionTest() {
+ @Before
+ fun assumeNotTv() {
+ assumeFalse(isTv)
+ }
+
+ @Before
+ fun installApp29() {
+ installPackage(APP_APK_PATH_29)
+ }
+
+ @Before
+ fun assertAppHasNoPermissions() {
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+ }
+
+ @Test
+ fun testRequestOnlyBackgroundNotPossible() {
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false,
+ waitForWindowTransition = false
+ ) {}
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+ }
+
+ @Test
+ fun testRequestBoth() {
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to true,
+ waitForWindowTransition = false
+ ) {
+ clickPermissionRequestSettingsLinkAndAllowAlways()
+ }
+ }
+
+ @Test
+ fun testRequestBothInSequence() {
+ // Step 1: request foreground only
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true
+ ) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+
+ // Step 2: request background only
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to true,
+ waitForWindowTransition = false
+ ) {
+ clickPermissionRequestSettingsLinkAndAllowAlways()
+ }
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, true)
+ }
+
+ @Test
+ fun testRequestBothButGrantInSequence() {
+ // Step 1: grant foreground only
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false
+ ) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ // Step 2: grant background
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to true,
+ waitForWindowTransition = false
+ ) {
+ clickPermissionRequestSettingsLinkAndAllowAlways()
+ }
+ }
+
+ @FlakyTest
+ @MtsIgnore
+ @Test
+ fun testDenyBackgroundWithPrejudice() {
+ // Step 1: deny the first time
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to false,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false
+ ) {
+ clickPermissionRequestDenyButton()
+ }
+
+ // Step 2: deny with prejudice
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to false,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false
+ ) {
+ clickPermissionRequestDenyAndDontAskAgainButton()
+ }
+
+ // Step 3: All further requests should be denied automatically
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to false,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @FlakyTest
+ @MtsIgnore
+ @Test
+ fun testGrantDialogToSettingsNoOp() {
+ // Step 1: Request both, go to settings, do nothing
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false,
+ waitForWindowTransition = false
+ ) {
+ openSettingsThenDoNothingThenLeave()
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+
+ doAndWaitForWindowTransition {
+ clickPermissionRequestAllowForegroundButton()
+ }
+ }
+
+ // Step 2: Upgrade foreground to background, go to settings, do nothing
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false,
+ waitForWindowTransition = false
+ ) {
+ openSettingsThenDoNothingThenLeave()
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, true)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+
+ doAndWaitForWindowTransition {
+ clickPermissionRequestNoUpgradeAndDontAskAgainButton()
+ }
+ }
+ }
+
+ private fun openSettingsThenDoNothingThenLeave() {
+ clickPermissionRequestSettingsLink()
+ eventually {
+ pressBack()
+ if (isAutomotive) {
+ waitFindObject(By.textContains("Allow in settings."), 100)
+ } else {
+ waitFindObject(By.res("com.android.permissioncontroller:id/grant_dialog"), 100)
+ }
+ }
+ }
+
+ @FlakyTest
+ @Test
+ fun testGrantDialogToSettingsDowngrade() {
+ // Request upgrade, downgrade permission to denied in settings
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.ACCESS_FINE_LOCATION to true,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION to false
+ ) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ requestAppPermissions(
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ waitForWindowTransition = false
+ ) {
+ clickPermissionRequestSettingsLinkAndDeny()
+ pressBack()
+ }
+
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, false)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30.kt
new file mode 100644
index 000000000..e6149bddc
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30.kt
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+/**
+ * Runtime permission behavior apps targeting API 30
+ */
+@FlakyTest
+class PermissionTest30 : BaseUsePermissionTest() {
+
+ @Test
+ fun testCantRequestFgAndBgAtOnce() {
+ // TODO(b/280542662): This delay is a temporary mitigation for an intermittent failure
+ Thread.sleep(500)
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_FINE_LOCATION to false,
+ ACCESS_BACKGROUND_LOCATION to false,
+ waitForWindowTransition = false
+ ) {
+ // Do nothing, should be automatically denied
+ }
+ }
+
+ @Test
+ fun testRequestBothInSequence() {
+ installPackage(APP_APK_PATH_30_WITH_BACKGROUND)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_BACKGROUND_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(ACCESS_FINE_LOCATION to true) {
+ clickPermissionRequestAllowForegroundButton()
+ }
+
+ requestAppPermissionsAndAssertResult(
+ ACCESS_BACKGROUND_LOCATION to true,
+ waitForWindowTransition = false
+ ) {
+ clickAllowAlwaysInSettings()
+ pressBack()
+ }
+ }
+
+ @Test
+ fun testRequestFgLocationAndNoAccuracyOptions() {
+ installPackage(APP_APK_PATH_30)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+
+ requestAppPermissionsAndAssertResult(ACCESS_FINE_LOCATION to false,
+ ACCESS_COARSE_LOCATION to false) {
+ // Verify there's no location accuracy options
+ val locationAccuracyOptions = waitFindObjectOrNull(By.res(
+ "com.android.permissioncontroller:id/permission_location_accuracy"), 1000L)
+ assertNull("For apps targetSDK < 31, location permission dialog shouldn't show " +
+ "accuracy options. Please update the system with " +
+ "the latest (at least Oct, 2021) mainline modules.",
+ locationAccuracyOptions)
+ // Close dialog
+ clickPermissionRequestDenyButton()
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30WithBluetooth.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30WithBluetooth.kt
new file mode 100644
index 000000000..2761755c9
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest30WithBluetooth.kt
@@ -0,0 +1,200 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.Manifest.permission.BLUETOOTH_SCAN
+import android.app.AppOpsManager
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothManager
+import android.bluetooth.cts.BTAdapterUtils
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
+import android.location.LocationManager
+import android.os.Build
+import android.os.Process
+import android.os.UserHandle
+import android.util.Log
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertTrue
+import junit.framework.AssertionFailedError
+import org.junit.After
+import org.junit.Assert.assertNotEquals
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+
+private const val LOG_TAG = "PermissionTest30WithBluetooth"
+
+/**
+ * Runtime Bluetooth-permission behavior of apps targeting API 30
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+@FlakyTest
+class PermissionTest30WithBluetooth : BaseUsePermissionTest() {
+
+ private val TEST_APP_AUTHORITY =
+ "android.permissionui.cts.usepermission.AccessBluetoothOnCommand"
+ private val TEST_APP_PKG =
+ "android.permissionui.cts.usepermission"
+ private lateinit var bluetoothAdapter: BluetoothAdapter
+ private var bluetoothAdapterWasEnabled: Boolean = false
+ private val locationManager = context.getSystemService(LocationManager::class.java)!!
+ private var locationWasEnabled: Boolean = false
+
+ private enum class BluetoothScanResult {
+ UNKNOWN, ERROR, EXCEPTION, EMPTY, FILTERED, FULL
+ }
+
+ @Before
+ fun installApp() {
+ installPackage(APP_APK_PATH_30_WITH_BLUETOOTH)
+ }
+
+ private fun reinstallApp() {
+ installPackage(APP_APK_PATH_30_WITH_BLUETOOTH, reinstall = true)
+ }
+
+ @Before
+ fun enableBluetooth() {
+ assumeTrue(supportsBluetooth())
+ bluetoothAdapter = context.getSystemService(BluetoothManager::class.java).adapter
+ bluetoothAdapterWasEnabled = bluetoothAdapter.isEnabled()
+ runWithShellPermissionIdentity {
+ assertTrue(BTAdapterUtils.enableAdapter(bluetoothAdapter, context))
+ }
+ enableTestMode()
+ }
+
+ @Before
+ fun enableLocation() {
+ val userHandle: UserHandle = Process.myUserHandle()
+ locationWasEnabled = locationManager.isLocationEnabledForUser(userHandle)
+ if (!locationWasEnabled) {
+ runWithShellPermissionIdentity {
+ locationManager.setLocationEnabledForUser(true, userHandle)
+ }
+ }
+ }
+
+ @After
+ fun disableLocation() {
+ val userHandle: UserHandle = Process.myUserHandle()
+
+ if (!locationWasEnabled) {
+ runWithShellPermissionIdentity {
+ locationManager.setLocationEnabledForUser(false, userHandle)
+ }
+ }
+ }
+
+ @After
+ fun disableBluetooth() {
+ assumeTrue(supportsBluetooth())
+ disableTestMode()
+ if (!bluetoothAdapterWasEnabled) {
+ runWithShellPermissionIdentity {
+ assertTrue(BTAdapterUtils.disableAdapter(bluetoothAdapter, context))
+ }
+ }
+ }
+
+ // TODO:(b/220030722) Remove verbose logging (after test is stabilized)
+ @Test
+ fun testGivenBluetoothIsDeniedWhenScanIsAttemptedThenThenGetEmptyScanResult() {
+ assumeTrue(supportsBluetoothLe())
+
+ assertTrue("Please enable location to run this test. Bluetooth scanning " +
+ "requires location to be enabled.", locationManager.isLocationEnabled())
+ assertBluetoothRevokedCompatState(revoked = false)
+
+ Log.v(LOG_TAG, "Testing for: Given {BLUETOOTH_SCAN, !BLUETOOTH_SCAN.COMPAT_REVOKE, " +
+ "!ACCESS_*_LOCATION}, expect EMPTY")
+ assertEquals(BluetoothScanResult.EMPTY, scanForBluetoothDevices())
+
+ Log.v(LOG_TAG, "Testing for: Given {BLUETOOTH_SCAN, !BLUETOOTH_SCAN.COMPAT_REVOKE, " +
+ "ACCESS_*_LOCATION}, expect FULL")
+ uiAutomation.grantRuntimePermission(TEST_APP_PKG, ACCESS_FINE_LOCATION)
+ uiAutomation.grantRuntimePermission(TEST_APP_PKG, ACCESS_BACKGROUND_LOCATION)
+ setAppOp(context.packageName, AppOpsManager.OPSTR_FINE_LOCATION, AppOpsManager.MODE_ALLOWED)
+ assertEquals(BluetoothScanResult.FULL, scanForBluetoothDevices())
+
+ Log.v(LOG_TAG, "Testing for: Given {BLUETOOTH_SCAN, BLUETOOTH_SCAN.COMPAT_REVOKE, " +
+ "ACCESS_*_LOCATION}, expect ERROR")
+ revokeAppPermissionsByUi(BLUETOOTH_SCAN, isLegacyApp = true)
+ assertBluetoothRevokedCompatState(revoked = true)
+ val res = scanForBluetoothDevices()
+ if (res != BluetoothScanResult.ERROR && res != BluetoothScanResult.EMPTY) {
+ throw AssertionFailedError("Expected to be EMPTY or ERROR, but was $res")
+ }
+ }
+
+ private fun setAppOp(packageName: String, appOp: String, appOpMode: Int) {
+ runWithShellPermissionIdentity {
+ context.getSystemService(AppOpsManager::class.java)!!.setUidMode(
+ appOp, packageManager.getPackageUid(packageName, 0), appOpMode)
+ }
+ }
+
+ @Test
+ fun testRevokedCompatPersistsOnReinstall() {
+ assertBluetoothRevokedCompatState(revoked = false)
+ revokeAppPermissionsByUi(BLUETOOTH_SCAN, isLegacyApp = true)
+ assertBluetoothRevokedCompatState(revoked = true)
+ reinstallApp()
+ assertBluetoothRevokedCompatState(revoked = true)
+ installApp()
+ assertBluetoothRevokedCompatState(revoked = true)
+ }
+
+ private fun assertBluetoothRevokedCompatState(revoked: Boolean = true) {
+ runWithShellPermissionIdentity {
+ val flag = context.packageManager.getPermissionFlags(BLUETOOTH_SCAN,
+ TEST_APP_PKG, Process.myUserHandle()) and FLAG_PERMISSION_REVOKED_COMPAT
+ if (revoked) {
+ assertNotEquals(0, flag)
+ } else {
+ assertEquals(0, flag)
+ }
+ }
+ }
+
+ private fun scanForBluetoothDevices(): BluetoothScanResult {
+ val resolver = InstrumentationRegistry.getTargetContext().getContentResolver()
+ val result = resolver.call(TEST_APP_AUTHORITY, "", null, null)
+ return BluetoothScanResult.values()[result!!.getInt(Intent.EXTRA_INDEX)]
+ }
+
+ private fun supportsBluetooth(): Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+
+ private fun supportsBluetoothLe(): Boolean =
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
+
+ private fun enableTestMode() = runShellCommandOrThrow("dumpsys activity service" +
+ " com.android.bluetooth.btservice.AdapterService set-test-mode enabled")
+
+ private fun disableTestMode() = runShellCommandOrThrow("dumpsys activity service" +
+ " com.android.bluetooth.btservice.AdapterService set-test-mode disabled")
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionUpgradeTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionUpgradeTest.kt
new file mode 100644
index 000000000..f153930f4
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionUpgradeTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015 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.permissionui.cts
+
+import androidx.test.filters.FlakyTest
+import org.junit.Assume
+import org.junit.Test
+
+/**
+ * Runtime permission behavior tests for upgrading apps.
+ */
+@FlakyTest
+class PermissionUpgradeTest : BaseUsePermissionTest() {
+
+ @Test
+ fun testUpgradeKeepsPermissions() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+
+ installPackage(APP_APK_PATH_22)
+
+ approvePermissionReview()
+
+ assertAllPermissionsGrantedByDefault()
+
+ installPackage(APP_APK_PATH_23, reinstall = true, skipClearLowSdkDialog = true)
+
+ assertAllPermissionsGrantedOnUpgrade()
+ }
+
+ private fun assertAllPermissionsGrantedByDefault() {
+ arrayOf(
+ android.Manifest.permission.SEND_SMS,
+ android.Manifest.permission.RECEIVE_SMS,
+ // The APK does not request READ_CONTACTS because of other tests
+ android.Manifest.permission.WRITE_CONTACTS,
+ android.Manifest.permission.READ_CALENDAR,
+ android.Manifest.permission.WRITE_CALENDAR,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.RECEIVE_WAP_PUSH,
+ android.Manifest.permission.RECEIVE_MMS,
+ "android.permission.READ_CELL_BROADCASTS",
+ android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.CALL_PHONE,
+ android.Manifest.permission.READ_CALL_LOG,
+ android.Manifest.permission.WRITE_CALL_LOG,
+ android.Manifest.permission.ADD_VOICEMAIL,
+ android.Manifest.permission.USE_SIP,
+ android.Manifest.permission.PROCESS_OUTGOING_CALLS,
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.BODY_SENSORS,
+ // Split permissions
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+ ).forEach {
+ assertAppHasPermission(it, true)
+ }
+ }
+
+ private fun assertAllPermissionsGrantedOnUpgrade() {
+ assertAppHasAllOrNoPermissions(true)
+ }
+
+ @Test
+ fun testNoDowngradePermissionModel() {
+ installPackage(APP_APK_PATH_23, skipClearLowSdkDialog = true)
+ installPackage(APP_APK_PATH_22, reinstall = true, expectSuccess = false)
+ }
+
+ @Test
+ fun testRevokePropagatedOnUpgradeOldToNewModel() {
+ Assume.assumeFalse(packageManager.arePermissionsIndividuallyControlled())
+
+ installPackage(APP_APK_PATH_22)
+
+ approvePermissionReview()
+
+ // Revoke a permission
+ revokeAppPermissionsByUi(android.Manifest.permission.WRITE_CALENDAR, isLegacyApp = true)
+
+ installPackage(APP_APK_PATH_23, reinstall = true, skipClearLowSdkDialog = true)
+
+ assertAppHasPermission(android.Manifest.permission.WRITE_CALENDAR, false)
+ }
+
+ @Test
+ fun testRevokePropagatedOnUpgradeNewToNewModel() {
+ installPackage(APP_APK_PATH_23)
+
+ // Make sure we don't have the permission
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
+ assertAppHasPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE, false)
+
+ // Request the permission and allow it
+ // Make sure the permission is granted
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.READ_CALENDAR to true,
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+
+ installPackage(APP_APK_PATH_23, reinstall = true, skipClearLowSdkDialog = true)
+
+ // Make sure the permission is still granted after the upgrade
+ assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, true)
+ // Also make sure one of the not granted permissions is still not granted
+ assertAppHasPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE, false)
+ }
+
+ private fun assertAppHasAllOrNoPermissions(expectPermissions: Boolean) {
+ arrayOf(
+ android.Manifest.permission.SEND_SMS,
+ android.Manifest.permission.RECEIVE_SMS,
+ android.Manifest.permission.RECEIVE_WAP_PUSH,
+ android.Manifest.permission.RECEIVE_MMS,
+ android.Manifest.permission.READ_CALENDAR,
+ android.Manifest.permission.WRITE_CALENDAR,
+ android.Manifest.permission.WRITE_CONTACTS,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_CALL_LOG,
+ android.Manifest.permission.WRITE_CALL_LOG,
+ android.Manifest.permission.ADD_VOICEMAIL,
+ android.Manifest.permission.CALL_PHONE,
+ android.Manifest.permission.USE_SIP,
+ android.Manifest.permission.PROCESS_OUTGOING_CALLS,
+ android.Manifest.permission.RECORD_AUDIO,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.CAMERA,
+ android.Manifest.permission.BODY_SENSORS,
+ android.Manifest.permission.READ_CELL_BROADCASTS,
+ // Split permissions
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ // Storage permissions
+ android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ).forEach {
+ assertAppHasPermission(it, expectPermissions)
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionUsageInfoTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionUsageInfoTest.kt
new file mode 100644
index 000000000..fafd50f2b
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionUsageInfoTest.kt
@@ -0,0 +1,58 @@
+/*
+ * 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.permissionui.cts
+
+import android.content.Intent
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests permission usage info action.
+ */
+@FlakyTest
+class PermissionUsageInfoTest : BaseUsePermissionTest() {
+ @Before
+ fun assumeHandheld() {
+ assumeFalse(isAutomotive)
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ }
+
+ @Before
+ fun installApp() {
+ installPackage(APP_APK_PATH_LATEST)
+ }
+
+ @Test
+ fun testPermissionUsageInfo() {
+ doAndWaitForWindowTransition {
+ runWithShellPermissionIdentity {
+ context.startActivity(
+ Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply {
+ putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+ )
+ }
+ }
+ click(By.res("com.android.permissioncontroller:id/icon"))
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerPermissionTest.kt
new file mode 100644
index 000000000..fa1fe61c6
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerPermissionTest.kt
@@ -0,0 +1,485 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_MEDIA_LOCATION
+import android.Manifest.permission.READ_MEDIA_IMAGES
+import android.Manifest.permission.READ_MEDIA_VIDEO
+import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME
+import android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
+import android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED
+import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
+import android.net.Uri
+import android.os.Build
+import android.provider.DeviceConfig
+import android.provider.DeviceConfig.NAMESPACE_PRIVACY
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import org.junit.AfterClass
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Test
+
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class PhotoPickerPermissionTest : BaseUsePermissionTest() {
+
+ companion object {
+ private var photoUri: Uri? = null
+ private var videoUri: Uri? = null
+ private var oldEnableState: Boolean = true
+
+ @BeforeClass
+ @JvmStatic
+ fun enablePickerAndAddMedia() {
+ // Initialize media provider package name
+ PhotoPickerUtils.getMediaProviderPkgName(context)
+ oldEnableState = isPhotoPickerPermissionPromptEnabled()
+ runWithShellPermissionIdentity {
+ if (!oldEnableState) {
+ DeviceConfig.setProperty(
+ NAMESPACE_PRIVACY, PICKER_ENABLED_SETTING, true.toString(), false)
+ }
+ photoUri = PhotoPickerUtils.createImage(context)
+ videoUri = PhotoPickerUtils.createVideo(context)
+ }
+ }
+
+ @AfterClass
+ @JvmStatic
+ fun resetPickerAndRemoveMedia() {
+ if (!oldEnableState) {
+ runWithShellPermissionIdentity {
+ DeviceConfig.setProperty(NAMESPACE_PRIVACY, PICKER_ENABLED_SETTING,
+ false.toString(), false)
+ }
+ }
+
+ PhotoPickerUtils.deleteMedia(context, photoUri)
+ PhotoPickerUtils.deleteMedia(context, videoUri)
+ }
+ }
+
+ @Before
+ fun assumeEnabled() {
+ assumeTrue(isPhotoPickerPermissionPromptEnabled())
+ }
+
+ @Test
+ fun testAppWithoutStoragePermsDoesntHaveUserSelectedAdded() {
+ installPackage(APP_APK_PATH_LATEST_NONE)
+ runWithShellPermissionIdentity {
+ val packageInfo =
+ packageManager.getPackageInfo(APP_PACKAGE_NAME, PackageManager.GET_PERMISSIONS)
+ assertNotNull(packageInfo)
+ val permissions = packageInfo.requestedPermissions?.toList() ?: emptyList<String>()
+ assertFalse(
+ "Expected app to not request READ_MEDIA_VISUAL_USER_SELECTED",
+ permissions.contains(READ_MEDIA_VISUAL_USER_SELECTED))
+ }
+ }
+
+ @Test
+ fun testAppWithStoragePermsHasUserSelectedAdded() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ runWithShellPermissionIdentity {
+ val packageInfo =
+ packageManager.getPackageInfo(APP_PACKAGE_NAME, PackageManager.GET_PERMISSIONS)
+ assertNotNull(packageInfo)
+ val permissions = packageInfo.requestedPermissions?.toList() ?: emptyList<String>()
+ assertTrue(
+ "Expected app to request READ_MEDIA_VISUAL_USER_SELECTED",
+ permissions.contains(READ_MEDIA_VISUAL_USER_SELECTED))
+ }
+ }
+
+ @Test
+ fun testAppWithUserSelectedPermShowsSelectOption() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissions(READ_MEDIA_IMAGES) {
+ assertNotNull(waitFindObjectOrNull(By.res(SELECT_BUTTON)))
+ click(By.res(DENY_BUTTON))
+ }
+ }
+
+ @Test
+ fun testNoPhotoSelectionTreatedAsCancel() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissionsAndAssertResult(
+ arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VISUAL_USER_SELECTED),
+ arrayOf(READ_MEDIA_IMAGES to false, READ_MEDIA_VISUAL_USER_SELECTED to false),
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ findImageOrVideo(expected = true)
+ uiDevice.pressBack()
+ }
+ assertPermissionFlags(READ_MEDIA_IMAGES, FLAG_PERMISSION_USER_SET to false)
+ assertPermissionFlags(READ_MEDIA_VISUAL_USER_SELECTED, FLAG_PERMISSION_USER_SET to false)
+ }
+
+ @Test
+ fun testImplicitUserSelectHasOneTimeGrantsWithoutAppOp() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissionsAndAssertResult(
+ arrayOf(READ_MEDIA_IMAGES),
+ arrayOf(READ_MEDIA_IMAGES to true),
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ clickAllow()
+ }
+ eventually {
+ // USER_SELECTED should be granted, but not returned in the result
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, expectPermission = true)
+ assertAppHasPermission(READ_MEDIA_VIDEO, expectPermission = true)
+ assertPermissionFlags(
+ READ_MEDIA_IMAGES,
+ FLAG_PERMISSION_ONE_TIME to true,
+ FLAG_PERMISSION_REVOKED_COMPAT to true)
+ assertPermissionFlags(
+ READ_MEDIA_VIDEO,
+ FLAG_PERMISSION_ONE_TIME to true,
+ FLAG_PERMISSION_REVOKED_COMPAT to true)
+ assertPermissionFlags(
+ READ_MEDIA_VISUAL_USER_SELECTED,
+ FLAG_PERMISSION_ONE_TIME to false,
+ FLAG_PERMISSION_REVOKED_COMPAT to false)
+ }
+ }
+
+ @Test
+ fun testImplicitShowsMorePhotosOnceSet() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ eventually {
+ uiAutomation.grantRuntimePermission(APP_PACKAGE_NAME, READ_MEDIA_VISUAL_USER_SELECTED)
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, true)
+ }
+
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ waitFindObject(By.res(DONT_SELECT_MORE_BUTTON))
+ uiDevice.pressBack()
+ }
+ }
+
+ @Test
+ fun testNonImplicitDoesntGrantOtherPermsWhenUserSelected() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VISUAL_USER_SELECTED),
+ arrayOf(READ_MEDIA_IMAGES to false, READ_MEDIA_VISUAL_USER_SELECTED to true),
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ clickAllow()
+ }
+
+ assertPermissionFlags(READ_MEDIA_IMAGES, FLAG_PERMISSION_USER_SET to true)
+ assertPermissionFlags(READ_MEDIA_VISUAL_USER_SELECTED, FLAG_PERMISSION_USER_SET to true)
+ }
+
+ @Test
+ fun testNonImplicitAutomaticallyShowsPickerWhenUserFixed() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ doAndWaitForWindowTransition {
+ clickAllow()
+ }
+ }
+
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ doAndWaitForWindowTransition {
+ clickAllow()
+ }
+ }
+
+ assertPermissionFlags(READ_MEDIA_VISUAL_USER_SELECTED, FLAG_PERMISSION_USER_FIXED to true)
+
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ findImageOrVideo(expected = true)
+ uiDevice.pressBack()
+ }
+ }
+
+ @Test
+ fun testRequestedPermsFilterMediaType() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ findImageOrVideo(expected = true)
+ findVideo(expected = false)
+ uiDevice.pressBack()
+ }
+
+ requestAppPermissions(READ_MEDIA_VIDEO, waitForWindowTransition = false) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ findVideo(expected = true)
+ uiDevice.pressBack()
+ }
+ }
+
+ @Test
+ fun testGrantAllPhotosStateSameForImplicitAndNot() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissionsAndAssertResult(arrayOf(READ_MEDIA_IMAGES),
+ arrayOf(READ_MEDIA_IMAGES to true)) {
+ click(By.res(ALLOW_ALL_BUTTON))
+ }
+
+ eventually {
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, expectPermission = true)
+ }
+
+ uninstallPackage(APP_PACKAGE_NAME)
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VISUAL_USER_SELECTED),
+ arrayOf(READ_MEDIA_IMAGES to true, READ_MEDIA_VISUAL_USER_SELECTED to true)) {
+ click(By.res(ALLOW_ALL_BUTTON))
+ }
+ }
+
+ @Test
+ fun testGrantAllPhotosInSettings() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ navigateToIndividualPermissionSetting(READ_MEDIA_IMAGES)
+ click(By.res(ALLOW_RADIO_BUTTON))
+
+ eventually {
+ assertAppHasPermission(READ_MEDIA_IMAGES, expectPermission = true)
+ assertAppHasPermission(READ_MEDIA_VIDEO, expectPermission = true)
+ assertAppHasPermission(ACCESS_MEDIA_LOCATION, expectPermission = true)
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, expectPermission = true)
+ }
+ }
+
+ @Test
+ fun testSelectPhotosInSettingsImplicit() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ navigateToIndividualPermissionSetting(READ_MEDIA_IMAGES)
+ click(By.res(SELECT_RADIO_BUTTON))
+
+ eventually {
+ assertAppHasPermission(READ_MEDIA_IMAGES, expectPermission = false)
+ assertAppHasPermission(READ_MEDIA_VIDEO, expectPermission = false)
+ assertAppHasPermission(ACCESS_MEDIA_LOCATION, expectPermission = false)
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, expectPermission = true)
+ }
+ }
+
+ @Test
+ fun testSelectPhotosInSettingsExplicit() {
+ installPackage(APP_APK_PATH_LATEST)
+ navigateToIndividualPermissionSetting(READ_MEDIA_IMAGES)
+ click(By.res(SELECT_RADIO_BUTTON))
+
+ eventually {
+ assertAppHasPermission(READ_MEDIA_IMAGES, expectPermission = false)
+ assertAppHasPermission(READ_MEDIA_VIDEO, expectPermission = false)
+ assertAppHasPermission(ACCESS_MEDIA_LOCATION, expectPermission = true)
+ assertAppHasPermission(READ_MEDIA_VISUAL_USER_SELECTED, expectPermission = true)
+ }
+ }
+
+ @Test
+ @Throws(PackageManager.NameNotFoundException::class)
+ fun testPre33AppDoesntShowSelect() {
+ installPackage(APP_APK_PATH_30)
+ runWithShellPermissionIdentity {
+ val requestedPerms = packageManager.getPackageInfo(APP_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS).requestedPermissions!!.toList()
+ assertTrue("Expected package to have USER_SELECTED",
+ requestedPerms.contains(READ_MEDIA_VISUAL_USER_SELECTED))
+ }
+
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ findView(By.res(SELECT_BUTTON), expected = false)
+ pressBack()
+ }
+
+ navigateToIndividualPermissionSetting(READ_MEDIA_IMAGES)
+ findView(By.res(SELECT_RADIO_BUTTON), expected = false)
+ }
+
+ @Test
+ fun test33AppWithImplicitUserSelectDoesntShowSelect() {
+ installPackage(APP_APK_PATH_STORAGE_33)
+
+ runWithShellPermissionIdentity {
+ val requestedPerms = packageManager.getPackageInfo(APP_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS).requestedPermissions!!.toList()
+ assertTrue("Expected package to have USER_SELECTED",
+ requestedPerms.contains(READ_MEDIA_VISUAL_USER_SELECTED))
+ }
+
+ requestAppPermissions(READ_MEDIA_IMAGES, waitForWindowTransition = false) {
+ findView(By.res(SELECT_BUTTON), expected = false)
+ pressBack()
+ }
+
+ navigateToIndividualPermissionSetting(READ_MEDIA_IMAGES)
+ findView(By.res(SELECT_RADIO_BUTTON), expected = false)
+ }
+
+ @Test
+ fun testAppCantRequestOnlyPartialStoragePerms() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_VISUAL_USER_SELECTED to false,
+ waitForWindowTransition = false
+ ) {}
+ uninstallPackage(APP_PACKAGE_NAME)
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_VISUAL_USER_SELECTED to false,
+ ACCESS_MEDIA_LOCATION to false,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testImplicitAppCanExpandAccessMediaLocation() {
+ installPackage(APP_APK_PATH_IMPLICIT_USER_SELECT_STORAGE)
+ requestAppPermissions(ACCESS_MEDIA_LOCATION) {
+ click(By.res(ALLOW_ALL_BUTTON))
+ }
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_IMAGES to true,
+ READ_MEDIA_VIDEO to true,
+ waitForWindowTransition = false
+ ) {}
+ }
+
+ @Test
+ fun testExplicitAppCannotExpandAccessMediaLocation() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_IMAGES to false,
+ ACCESS_MEDIA_LOCATION to true,
+ READ_MEDIA_VISUAL_USER_SELECTED to true,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ clickAllow()
+ }
+ requestAppPermissions(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO) {
+ click(By.res(ALLOW_ALL_BUTTON))
+ }
+ }
+
+ @Test
+ fun testExplicitAppCannotRequestOnlyPartialAccess() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ ACCESS_MEDIA_LOCATION to false,
+ READ_MEDIA_VISUAL_USER_SELECTED to false,
+ waitForWindowTransition = false
+ ) {
+ findView(By.res(SELECT_BUTTON), expected = false)
+ }
+ }
+
+ @Test
+ fun testMorePhotosDialogShowsAfterClickingSelect() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_IMAGES to false,
+ ACCESS_MEDIA_LOCATION to true, READ_MEDIA_VISUAL_USER_SELECTED to true,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ doAndWaitForWindowTransition {
+ clickAllow()
+ }
+ }
+
+ requestAppPermissions(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO) {
+ findView(By.res(DONT_SELECT_MORE_BUTTON), expected = true)
+ click(By.res(ALLOW_ALL_BUTTON))
+ }
+ }
+
+ @Test
+ fun testAMLNotGrantedIfNotRequested() {
+ installPackage(APP_APK_PATH_LATEST)
+ requestAppPermissionsAndAssertResult(
+ READ_MEDIA_IMAGES to false,
+ READ_MEDIA_VISUAL_USER_SELECTED to true,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition {
+ click(By.res(SELECT_BUTTON))
+ }
+ clickImageOrVideo()
+ doAndWaitForWindowTransition {
+ clickAllow()
+ }
+ }
+ assertAppHasPermission(ACCESS_MEDIA_LOCATION, false)
+ }
+
+ private fun clickImageOrVideo() {
+ click(By.res(PhotoPickerUtils.getImageOrVideoResId(context)))
+ }
+
+ private fun clickAllow() {
+ click(By.res(PhotoPickerUtils.getAllowId(context)))
+ }
+
+ private fun findImageOrVideo(expected: Boolean) {
+ findView(By.res(PhotoPickerUtils.getImageOrVideoResId(context)), expected)
+ }
+
+ private fun findVideo(expected: Boolean) {
+ findView(By.res(PhotoPickerUtils.getVideoResId(context)), expected)
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerUtils.kt b/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerUtils.kt
new file mode 100644
index 000000000..0b9e54f86
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PhotoPickerUtils.kt
@@ -0,0 +1,117 @@
+/*
+ * 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.permissionui.cts
+
+import android.content.Context
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.os.FileUtils
+import android.provider.MediaStore
+import android.provider.cts.ProviderTestUtils
+import android.provider.cts.media.MediaStoreUtils
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import java.io.IOException
+
+object PhotoPickerUtils {
+ private const val DISPLAY_NAME_PREFIX = "ctsPermissionPhotoPicker"
+ private const val VIDEO_ICON_ID = ":id/icon_video"
+ private const val IMAGE_CHECK_BOX_ID = ":id/icon_check"
+ private const val ALLOW_ID = ":id/button_add"
+ private var mediaProviderPkgName: String? = null
+
+ fun getImageOrVideoResId(context: Context): String {
+ return "${getMediaProviderPkgName(context)!!}$IMAGE_CHECK_BOX_ID"
+ }
+
+ fun getVideoResId(context: Context): String {
+ return "${getMediaProviderPkgName(context)!!}$VIDEO_ICON_ID"
+ }
+
+ fun getAllowId(context: Context): String {
+ return "${getMediaProviderPkgName(context)!!}$ALLOW_ID"
+ }
+
+ fun getMediaProviderPkgName(context: Context): String? {
+ return mediaProviderPkgName ?: callWithShellPermissionIdentity {
+ val pkgs = context.packageManager.getInstalledPackages(PackageManager.GET_PROVIDERS)
+ for (pkg in pkgs) {
+ pkg.providers?.let { providerInfos ->
+ for (providerInfo in providerInfos) {
+ if (providerInfo.authority == "media") {
+ mediaProviderPkgName = pkg.packageName
+ return@callWithShellPermissionIdentity mediaProviderPkgName
+ }
+ }
+ }
+ }
+ null
+ }
+ }
+
+ @Throws(java.lang.Exception::class)
+ fun createImage(context: Context): Uri {
+ return getPermissionAndStageMedia( context, R.raw.lg_g4_iso_800_jpg,
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg").first
+ }
+
+ @Throws(java.lang.Exception::class)
+ fun createVideo(context: Context): Uri {
+ return getPermissionAndStageMedia(context, R.raw.test_video,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4").first
+ }
+
+ @Throws(Exception::class)
+ fun deleteMedia(context: Context, uri: Uri?) {
+ if (uri == null) {
+ return
+ }
+ try {
+ ProviderTestUtils.setOwner(uri, context.packageName)
+ context.contentResolver.delete(uri, Bundle.EMPTY)
+ } catch (ignored: Exception) {}
+ }
+
+ @Throws(java.lang.Exception::class)
+ private fun getPermissionAndStageMedia(
+ context: Context,
+ resId: Int,
+ collectionUri: Uri,
+ mimeType: String,
+ ): Pair<Uri, String> {
+ return callWithShellPermissionIdentity {
+ stageMedia(context, resId, collectionUri, mimeType)
+ }
+ }
+ @Throws(IOException::class)
+ private fun stageMedia(
+ context: Context,
+ resId: Int,
+ collectionUri: Uri,
+ mimeType: String,
+ ): Pair<Uri, String> {
+ val displayName = DISPLAY_NAME_PREFIX + System.nanoTime()
+ val params = MediaStoreUtils.PendingParams(collectionUri, displayName, mimeType)
+ val pendingUri = MediaStoreUtils.createPending(context, params)
+ MediaStoreUtils.openPending(context, pendingUri).use { session ->
+ context.resources.openRawResource(resId).use { source ->
+ session.openOutputStream().use { target -> FileUtils.copy(source, target) }
+ }
+ return session.publish() to displayName
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt
new file mode 100644
index 000000000..70831fd41
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/ReviewAccessibilityServicesTest.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService
+import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule
+import android.app.UiAutomation
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.platform.test.annotations.AppModeFull
+import androidx.test.filters.FlakyTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Configurator
+import androidx.test.uiautomator.StaleObjectException
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
+import java.util.regex.Pattern
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@AppModeFull(reason = "Instant apps cannot be a11y services")
+@FlakyTest
+class ReviewAccessibilityServicesTest {
+
+ private val context: Context = InstrumentationRegistry.getInstrumentation().context
+ private val uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ private val testService1String = context.getString(R.string.test_accessibility_service)
+ private val testService2String = context.getString(R.string.test_accessibility_service_2)
+
+ companion object {
+ private const val EXPECTED_TIMEOUT_MS = 500L
+ private const val NEW_WINDOW_TIMEOUT_MILLIS: Long = 20_000
+ }
+
+ @get:Rule
+ val accessibilityServiceRule =
+ InstrumentedAccessibilityServiceTestRule(AccessibilityTestService1::class.java, false)
+
+ @get:Rule
+ val accessibilityServiceRule2 =
+ InstrumentedAccessibilityServiceTestRule(AccessibilityTestService2::class.java, false)
+
+ init {
+ Configurator.getInstance().uiAutomationFlags =
+ UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES
+ }
+
+ @Before
+ fun assumeNotAutoTvOrWear() {
+ Assume.assumeFalse(context.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ Assume.assumeFalse(
+ context.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ Assume.assumeFalse(context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH))
+ }
+
+ @After
+ fun cleanUp() {
+ uiDevice.pressHome()
+ }
+
+ @Test
+ fun testActivityShowsSingleEnabledAccessibilityService() {
+ accessibilityServiceRule.enableService()
+ startAccessibilityActivity()
+ findTestService(true)
+ findTestService2(false)
+ }
+
+ @Test
+ fun testActivityShowsMultipleEnabledAccessibilityServices() {
+ accessibilityServiceRule.enableService()
+ accessibilityServiceRule2.enableService()
+ startAccessibilityActivity()
+ findTestService(true)
+ findTestService2(true)
+ }
+
+ @Test
+ fun testClickingSettingsGoesToIndividualSettingsWhenOneServiceEnabled() {
+ accessibilityServiceRule.enableService()
+ startAccessibilityActivity()
+ clickSettings()
+ waitForSettingsButtonToDisappear()
+ findTestService(true)
+ findTestService2(false)
+ }
+
+ @Test
+ @Ignore("b/293507233")
+ fun testClickingSettingsGoesToGeneralSettingsWhenMultipleServicesEnabled() {
+ accessibilityServiceRule.enableService()
+ accessibilityServiceRule2.enableService()
+ startAccessibilityActivity()
+ clickSettings()
+ waitForSettingsButtonToDisappear()
+ findTestService(true)
+ findTestService2(true)
+ }
+
+ @Test
+ fun testClickingIndividualGoesToIndividualSettingsWhenMultipleServicesEnabled() {
+ accessibilityServiceRule.enableService()
+ accessibilityServiceRule2.enableService()
+ startAccessibilityActivity()
+ findTestService2(true)!!.click()
+ waitForSettingsButtonToDisappear()
+ findTestService2(true)
+ findTestService(false)
+ }
+
+ private fun startAccessibilityActivity() {
+ val automan =
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES)
+ doAndWaitForWindowTransition {
+ automan.adoptShellPermissionIdentity()
+ try {
+ context.startActivity(
+ Intent(Intent.ACTION_REVIEW_ACCESSIBILITY_SERVICES)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK))
+ } catch (e: Exception) {
+ throw RuntimeException("Caught exception", e)
+ } finally {
+ automan.dropShellPermissionIdentity()
+ }
+ }
+ }
+
+ private inline fun doAndWaitForWindowTransition(
+ crossinline block: () -> Unit
+ ) {
+ val timeoutOccurred: Boolean = !uiDevice.performActionAndWait({
+ block()
+ }, Until.newWindow(), NEW_WINDOW_TIMEOUT_MILLIS)
+
+ if (timeoutOccurred) {
+ throw RuntimeException("Timed out waiting for window transition.")
+ }
+ }
+
+ private fun findTestService(shouldBePresent: Boolean): UiObject2? {
+ return findObjectByText(shouldBePresent, testService1String)
+ }
+
+ private fun findTestService2(shouldBePresent: Boolean): UiObject2? {
+ return findObjectByText(shouldBePresent, testService2String)
+ }
+
+ private fun clickSettings() {
+ findObjectByText(true, "Settings")?.click()
+ }
+
+ private fun waitForSettingsButtonToDisappear() {
+ SystemUtil.eventually {
+ findObjectByText(false, "Settings")
+ }
+ }
+
+ private fun findObjectByTextWithoutRetry(shouldBePresent: Boolean, text: String, ): UiObject2? {
+ val containsWithoutCaseSelector =
+ By.text(Pattern.compile(".*$text.*", Pattern.CASE_INSENSITIVE))
+ val view = if (shouldBePresent) {
+ waitFindObjectOrNull(containsWithoutCaseSelector)
+ } else {
+ waitFindObjectOrNull(containsWithoutCaseSelector, EXPECTED_TIMEOUT_MS)
+ }
+
+ assertEquals("Expected to find view with text $text: $shouldBePresent",
+ shouldBePresent, view != null)
+ return view
+ }
+
+ private fun findObjectByText(expected: Boolean, text: String): UiObject2? {
+ try {
+ return findObjectByTextWithoutRetry(expected, text)
+ } catch (stale: StaleObjectException) {
+ return findObjectByTextWithoutRetry(expected, text)
+ }
+ }
+}
+
+/** Test Accessibility Services */
+class AccessibilityTestService1 : InstrumentedAccessibilityService()
+
+class AccessibilityTestService2 : InstrumentedAccessibilityService()
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt
new file mode 100644
index 000000000..1840abf1b
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/SafetyLabelChangesJobServiceTest.kt
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.app.Instrumentation
+import android.app.UiAutomation
+import android.content.Context
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_OTHER
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_STORE
+import android.content.pm.PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.PersistableBundle
+import android.os.Process
+import android.permission.cts.CtsNotificationListenerHelperRule
+import android.permission.cts.CtsNotificationListenerServiceUtils
+import android.permission.cts.CtsNotificationListenerServiceUtils.getNotification
+import android.permission.cts.CtsNotificationListenerServiceUtils.getNotificationForPackageAndId
+import android.permission.cts.PermissionUtils
+import android.permission.cts.TestUtils
+import android.permissionui.cts.AppMetadata.createAppMetadataWithLocationSharingNoAds
+import android.permissionui.cts.AppMetadata.createAppMetadataWithNoSharing
+import android.provider.DeviceConfig
+import android.safetylabel.SafetyLabelConstants
+import android.safetylabel.SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.compatibility.common.util.SystemUtil
+import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.compatibility.common.util.SystemUtil.waitForBroadcasts
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+
+/** End-to-end test for SafetyLabelChangesJobService. */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+@FlakyTest
+class SafetyLabelChangesJobServiceTest : BaseUsePermissionTest() {
+
+ @get:Rule
+ val safetyLabelChangeNotificationsEnabledConfig =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SafetyLabelConstants.SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED,
+ true.toString())
+
+ /**
+ * This rule serves to limit the max number of safety labels that can be persisted, so that
+ * repeated tests don't overwhelm the disk storage on the device.
+ */
+ @get:Rule
+ val deviceConfigMaxSafetyLabelsPersistedPerApp =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_MAX_SAFETY_LABELS_PERSISTED_PER_APP,
+ "2")
+
+ @get:Rule
+ val deviceConfigDataSharingUpdatesPeriod =
+ DeviceConfigStateChangerRule(
+ BasePermissionTest.context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ PROPERTY_DATA_SHARING_UPDATE_PERIOD_MILLIS,
+ "600000")
+
+ @Before
+ fun setup() {
+ val packageManager = context.packageManager
+ Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH))
+
+ SystemUtil.runShellCommand("input keyevent KEYCODE_WAKEUP")
+ SystemUtil.runShellCommand("wm dismiss-keyguard")
+
+ // Bypass battery saving restrictions
+ SystemUtil.runShellCommand(
+ "cmd tare set-vip " +
+ "${Process.myUserHandle().identifier} $permissionControllerPackageName true")
+ CtsNotificationListenerServiceUtils.cancelNotifications(permissionControllerPackageName)
+ resetPermissionControllerAndSimulateReboot()
+ }
+
+ @After
+ fun cancelJobsAndNotifications() {
+ cancelJob(SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID)
+ cancelJob(SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID)
+ CtsNotificationListenerServiceUtils.cancelNotifications(permissionControllerPackageName)
+ // Reset battery saving restrictions
+ SystemUtil.runShellCommand(
+ "cmd tare set-vip " +
+ "${Process.myUserHandle().identifier} $permissionControllerPackageName default")
+ }
+
+ @Test
+ fun runDetectUpdatesJob_initializesSafetyLabelsHistoryForApps() {
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app install is
+ // identified and recorded.
+ runDetectUpdatesJob()
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+
+ assertNotificationNotShown()
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_initializesSafetyLabelsHistoryForApps() {
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app install is
+ // identified and recorded.
+ runNotificationJob()
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runDetectUpdatesJob_updatesSafetyLabelHistoryForApps() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runDetectUpdatesJob()
+
+ assertNotificationNotShown()
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_updatesSafetyLabelHistoryForApps() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_whenLocationSharingUpdatesForLocationGrantedApps_showsNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ waitForBroadcasts()
+ // TODO(b/279455955): Investigate why this is necessary and remove if possible.
+ Thread.sleep(500)
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ runNotificationJob()
+
+ waitForNotificationShown()
+
+ val statusBarNotification = getNotification(permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_NOTIFICATION_ID)
+ val contentIntent = statusBarNotification!!.notification.contentIntent
+ contentIntent.send()
+
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_whenNoLocationGrantedApps_doesNotShowNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ waitForBroadcasts()
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds())
+ waitForBroadcasts()
+
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @Test
+ fun runNotificationJob_whenNoLocationSharingUpdates_doesNotShowNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing())
+ waitForBroadcasts()
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @Test
+ fun runNotificationJob_packageSourceUnspecified_updatesSafetyLabelHistoryForApps() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_UNSPECIFIED)
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_UNSPECIFIED)
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_packageSourceOther_doesNotShowNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_OTHER)
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_OTHER)
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @Test
+ fun runNotificationJob_packageSourceStore_updatesSafetyLabelHistoryForApps() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_STORE)
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_STORE)
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertDataSharingScreenHasUpdates()
+ }
+
+ @Test
+ fun runNotificationJob_packageSourceLocalFile_doesNotShowNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_LOCAL_FILE)
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_LOCAL_FILE)
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ @Test
+ fun runNotificationJob_packageSourceDownloadedFile_udoesNotShowNotification() {
+ installPackageViaSession(APP_APK_NAME_31, createAppMetadataWithNoSharing(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE)
+ waitForBroadcastReceiverFinished()
+ installPackageNoBroadcast(APP_APK_NAME_31, createAppMetadataWithLocationSharingNoAds(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE)
+ grantLocationPermission(APP_PACKAGE_NAME)
+
+ // Run the job to check whether the missing safety label for the above app update is
+ // identified and recorded.
+ runNotificationJob()
+
+ assertNotificationNotShown()
+ }
+
+ private fun grantLocationPermission(packageName: String) {
+ uiAutomation.grantRuntimePermission(
+ packageName, android.Manifest.permission.ACCESS_FINE_LOCATION)
+ }
+
+ private fun installPackageNoBroadcast(
+ apkName: String,
+ appMetadata: PersistableBundle? = null,
+ packageSource: Int? = null
+ ) {
+ // Disable the safety labels feature during install to simulate installing an app without
+ // receiving an update about the change to its safety label.
+ setDeviceConfigPrivacyProperty(SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, false.toString())
+ installPackageViaSession(apkName, appMetadata, packageSource)
+ waitForBroadcastReceiverFinished()
+ setDeviceConfigPrivacyProperty(SAFETY_LABEL_CHANGE_NOTIFICATIONS_ENABLED, true.toString())
+ }
+
+ private fun assertDataSharingScreenHasUpdates() {
+ startAppDataSharingUpdatesActivity()
+ try {
+ findView(By.descContains(DATA_SHARING_UPDATES), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_SUBTITLE), true)
+ findView(By.textContains(UPDATES_IN_LAST_30_DAYS), true)
+ findView(By.textContains(APP_PACKAGE_NAME_SUBSTRING), true)
+ findView(By.textContains(DATA_SHARING_UPDATES_FOOTER_MESSAGE), true)
+ } finally {
+ pressBack()
+ }
+ }
+
+ companion object {
+ private const val TIMEOUT_TIME_MS = 60_000L
+ private const val SHORT_SLEEP_MS = 2000L
+
+ private const val SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID = 8
+ private const val SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID = 9
+ private const val SET_UP_SAFETY_LABEL_CHANGES_JOB =
+ "com.android.permissioncontroller.action.SET_UP_SAFETY_LABEL_CHANGES_JOB"
+ private const val SAFETY_LABEL_CHANGES_JOB_SERVICE_RECEIVER_CLASS =
+ "com.android.permissioncontroller.permission.service.v34" +
+ ".SafetyLabelChangesJobService\$Receiver"
+ private const val SAFETY_LABEL_CHANGES_NOTIFICATION_ID = 5
+ private const val JOB_STATUS_UNKNOWN = "unknown"
+ private const val JOB_STATUS_ACTIVE = "active"
+ private const val JOB_STATUS_WAITING = "waiting"
+
+ private val context: Context = InstrumentationRegistry.getTargetContext()
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private fun uiAutomation(): UiAutomation = instrumentation.uiAutomation
+ private val permissionControllerPackageName =
+ context.packageManager.permissionControllerPackageName
+ private val userId = Process.myUserHandle().identifier
+
+ @get:ClassRule
+ @JvmStatic
+ val ctsNotificationListenerHelper =
+ CtsNotificationListenerHelperRule(
+ InstrumentationRegistry.getInstrumentation().targetContext)
+
+ private fun waitForNotificationShown() {
+ eventually {
+ val notification = getNotification(false)
+ assertThat(notification).isNotNull()
+ }
+ }
+
+ private fun assertNotificationNotShown() {
+ eventually {
+ val notification = getNotification(false)
+ assertThat(notification).isNull()
+ }
+ }
+
+ private fun getNotification(cancelNotification: Boolean) =
+ getNotificationForPackageAndId(
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_NOTIFICATION_ID,
+ cancelNotification)
+ ?.notification
+
+ private fun cancelJob(jobId: Int) {
+ SystemUtil.runShellCommandOrThrow(
+ "cmd jobscheduler cancel -u $userId $permissionControllerPackageName $jobId")
+ TestUtils.awaitJobUntilRequestedState(
+ permissionControllerPackageName,
+ jobId,
+ TIMEOUT_TIME_MS,
+ uiAutomation(),
+ JOB_STATUS_UNKNOWN)
+ }
+
+ private fun runDetectUpdatesJob() {
+ startJob(SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID)
+ TestUtils.awaitJobUntilRequestedState(
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID,
+ TIMEOUT_TIME_MS,
+ uiAutomation(),
+ JOB_STATUS_ACTIVE)
+ TestUtils.awaitJobUntilRequestedState(
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID,
+ TIMEOUT_TIME_MS,
+ uiAutomation(),
+ JOB_STATUS_UNKNOWN)
+ }
+
+ private fun runNotificationJob() {
+ startJob(SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID)
+ TestUtils.awaitJobUntilRequestedState(
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID,
+ TIMEOUT_TIME_MS,
+ uiAutomation(),
+ JOB_STATUS_ACTIVE)
+ // TODO(b/266449833): In theory we should only have to wait for "waiting" here, but
+ // sometimes jobscheduler returns "unknown".
+ TestUtils.awaitJobUntilRequestedState(
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID,
+ TIMEOUT_TIME_MS,
+ uiAutomation(),
+ JOB_STATUS_WAITING,
+ JOB_STATUS_UNKNOWN)
+ }
+
+ private fun startJob(jobId: Int) {
+ val runJobCmd = "cmd jobscheduler run -u $userId -f " +
+ "$permissionControllerPackageName $jobId"
+ try {
+ SystemUtil.runShellCommandOrThrow(runJobCmd)
+ } catch (e: Throwable) {
+ throw RuntimeException(e)
+ }
+ }
+
+ private fun resetPermissionControllerAndSimulateReboot() {
+ PermissionUtils.resetPermissionControllerJob(
+ uiAutomation(),
+ permissionControllerPackageName,
+ SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID,
+ TIMEOUT_TIME_MS,
+ SET_UP_SAFETY_LABEL_CHANGES_JOB,
+ SAFETY_LABEL_CHANGES_JOB_SERVICE_RECEIVER_CLASS)
+ }
+
+ private fun waitForBroadcastReceiverFinished() {
+ waitForBroadcasts()
+ // Add a short sleep to ensure that the SafetyLabelChangedBroadcastReceiver finishes its
+ // work based according to the current feature flag value before changing the flag value.
+ // While `waitForBroadcasts()` waits for broadcasts to be dispatched, it will not wait for
+ // the receivers' `onReceive` to finish.
+ Thread.sleep(SHORT_SLEEP_MS)
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/SafetyProtectionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/SafetyProtectionTest.kt
new file mode 100644
index 000000000..8515dc1b7
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/SafetyProtectionTest.kt
@@ -0,0 +1,123 @@
+
+/*
+ * Copyright (C) 2023 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.permissionui.cts
+
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
+import android.Manifest.permission.ACCESS_FINE_LOCATION
+import android.content.res.Resources
+import android.provider.DeviceConfig
+import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.DeviceConfigStateChangerRule
+import com.android.modules.utils.build.SdkLevel
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+/**
+ * Tests for Safety Protection related features. This feature should only be enabled on T+.
+ */
+@FlakyTest
+class SafetyProtectionTest : BaseUsePermissionTest() {
+ @get:Rule
+ val safetyProtectionEnabled =
+ DeviceConfigStateChangerRule(
+ context,
+ DeviceConfig.NAMESPACE_PRIVACY,
+ SAFETY_PROTECTION_ENABLED_FLAG,
+ true.toString()
+ )
+
+ @Before
+ fun setup() {
+ assumeFalse(isAutomotive)
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ }
+
+ @Ignore("b/276944839")
+ @Test
+ fun testSafetyProtectionSectionView_safetyProtection_belowT() {
+ assumeFalse("Safety Protection should only be enabled on T+", SdkLevel.isAtLeastT())
+ installPackageViaSession(APP_APK_NAME_31)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ findView(By.res(SAFETY_PROTECTION_DISPLAY_TEXT), false)
+ }
+ }
+
+ @Test
+ fun testSafetyProtectionSectionView_safetyProtectionDisabled_aboveT() {
+ assumeTrue("Safety Protection should only be enabled on T+", SdkLevel.isAtLeastT())
+ setDeviceConfigPrivacyProperty(SAFETY_PROTECTION_ENABLED_FLAG, false.toString())
+ installPackageViaSession(APP_APK_NAME_31)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ findView(By.res(SAFETY_PROTECTION_DISPLAY_TEXT), false)
+ }
+ }
+
+ @Test
+ fun testSafetyProtectionSectionView_safetyProtectionEnabled_aboveT() {
+ assumeTrue("Safety Protection should only be enabled on T+", SdkLevel.isAtLeastT())
+ assumeTrue(safetyProtectionResourcesExist)
+ installPackageViaSession(APP_APK_NAME_31)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ findView(By.res(SAFETY_PROTECTION_DISPLAY_TEXT), true)
+ }
+ }
+
+ @Test
+ fun testSafetyProtectionSectionView_safetyProtectionResourcesNotExist_aboveT() {
+ assumeTrue("Safety Protection should only be enabled on T+", SdkLevel.isAtLeastT())
+ assumeFalse(safetyProtectionResourcesExist)
+ installPackageViaSession(APP_APK_NAME_31)
+ assertAppHasPermission(ACCESS_COARSE_LOCATION, false)
+ assertAppHasPermission(ACCESS_FINE_LOCATION, false)
+ requestAppPermissionsForNoResult(ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION) {
+ findView(By.res(SAFETY_PROTECTION_DISPLAY_TEXT), false)
+ }
+ }
+
+ companion object {
+ private const val SAFETY_PROTECTION_ENABLED_FLAG = "safety_protection_enabled"
+ private const val SAFETY_PROTECTION_DISPLAY_TEXT =
+ "com.android.permissioncontroller:id/safety_protection_display_text"
+ private val safetyProtectionResourcesExist =
+ try {
+ context
+ .getResources()
+ .getBoolean(
+ Resources.getSystem()
+ .getIdentifier("config_safetyProtectionEnabled", "bool", "android")
+ ) &&
+ context.getDrawable(android.R.drawable.ic_safety_protection) != null &&
+ !context.getString(
+ android.R.string.safety_protection_display_text
+ ).isNullOrEmpty()
+ } catch (e: Resources.NotFoundException) {
+ false
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/SensorBlockedBannerTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/SensorBlockedBannerTest.kt
new file mode 100644
index 000000000..4845d3007
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/SensorBlockedBannerTest.kt
@@ -0,0 +1,172 @@
+/*
+ * 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.permissionui.cts
+
+import android.Manifest.permission_group.CAMERA as CAMERA_PERMISSION_GROUP
+import android.Manifest.permission_group.LOCATION as LOCATION_PERMISSION_GROUP
+import android.Manifest.permission_group.MICROPHONE as MICROPHONE_PERMISSION_GROUP
+import android.content.Intent
+import android.hardware.SensorPrivacyManager
+import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
+import android.location.LocationManager
+import android.os.Build
+import android.safetycenter.SafetyCenterManager
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.uiautomator.By
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import java.util.regex.Pattern
+import org.junit.Assert.assertTrue
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Banner card display tests on sensors being blocked
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
+@FlakyTest
+class SensorBlockedBannerTest : BaseUsePermissionTest() {
+ companion object {
+ const val LOCATION = -1
+ const val DELAY_MILLIS = 3000L
+ private const val CHANGE_BUTTON = "com.android.permissioncontroller:id/button_id"
+ private const val CAMERA_TOGGLE_LABEL = "Camera access"
+ }
+
+ private val sensorPrivacyManager = context.getSystemService(SensorPrivacyManager::class.java)!!
+ private val locationManager = context.getSystemService(LocationManager::class.java)!!
+ private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
+
+ private val sensorToPermissionGroup = mapOf(CAMERA to CAMERA_PERMISSION_GROUP,
+ MICROPHONE to MICROPHONE_PERMISSION_GROUP,
+ LOCATION to LOCATION_PERMISSION_GROUP)
+
+ private val permToTitle = mapOf(CAMERA to "blocked_camera_title",
+ MICROPHONE to "blocked_microphone_title",
+ LOCATION to "blocked_location_title")
+
+ @Before
+ fun setup() {
+ Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
+ // TODO(b/203784852) Auto will eventually support the blocked sensor banner, but there won't
+ // be support in T or below
+ Assume.assumeFalse(isAutomotive)
+ installPackage(APP_APK_PATH_31)
+ }
+
+ private fun navigateAndTest(sensor: Int) {
+ val permissionGroup = sensorToPermissionGroup.getOrDefault(sensor, "Break")
+ val intent = Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroup)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ runWithShellPermissionIdentity {
+ context.startActivity(intent)
+ }
+ val bannerTitle = permToTitle.getOrDefault(sensor, "Break")
+ waitFindObject(By.text(getPermissionControllerString(bannerTitle)))
+ }
+
+ private fun runSensorTest(sensor: Int) {
+ var blocked = false
+ try {
+ blocked = isSensorPrivacyEnabled(sensor)
+ if (!blocked) {
+ setSensor(sensor, true)
+ }
+ navigateAndTest(sensor)
+ } finally {
+ if (!blocked) {
+ setSensor(sensor, false)
+ }
+ }
+ }
+
+ @Test
+ fun testCameraCardDisplayed() {
+ Assume.assumeTrue(sensorPrivacyManager.supportsSensorToggle(CAMERA))
+ runSensorTest(CAMERA)
+ }
+
+ @Test
+ fun testMicCardDisplayed() {
+ Assume.assumeTrue(sensorPrivacyManager.supportsSensorToggle(MICROPHONE))
+ runSensorTest(MICROPHONE)
+ }
+
+ @Test
+ fun testLocationCardDisplayed() {
+ runSensorTest(LOCATION)
+ }
+
+ @Test
+ fun testCardClickOpenPrivacyControls() {
+ Assume.assumeTrue(sensorPrivacyManager.supportsSensorToggle(CAMERA))
+ runWithShellPermissionIdentity {
+ Assume.assumeTrue(safetyCenterManager.isSafetyCenterEnabled)
+ }
+ // Disable global camera toggle
+ val blocked = isSensorPrivacyEnabled(CAMERA)
+ if (!blocked) {
+ setSensor(CAMERA, true)
+ }
+ // verify sensor card is shown for blocked camera
+ navigateAndTest(CAMERA)
+ click(By.res(CHANGE_BUTTON))
+ // Enable global camera toggle and verify
+ waitFindObject(By.text(CAMERA_TOGGLE_LABEL)).click()
+ assertTrue(!isSensorPrivacyEnabled(CAMERA))
+ }
+
+ private fun setSensor(sensor: Int, enable: Boolean) {
+ if (sensor == LOCATION) {
+ runWithShellPermissionIdentity {
+ locationManager.setLocationEnabledForUser(!enable,
+ android.os.Process.myUserHandle())
+ if (enable) {
+ try {
+ val closePattern = Pattern.compile("close", Pattern.CASE_INSENSITIVE)
+ waitFindObjectOrNull(By.text(closePattern), DELAY_MILLIS)?.click()
+ } catch (e: Exception) {
+ // Do nothing, warning didn't show up so test can proceed
+ }
+ }
+ }
+ } else {
+ runWithShellPermissionIdentity {
+ sensorPrivacyManager.setSensorPrivacy(SensorPrivacyManager.Sources.OTHER,
+ sensor, enable)
+ }
+ }
+ }
+
+ private fun isSensorPrivacyEnabled(sensor: Int): Boolean {
+ return if (sensor == LOCATION) {
+ callWithShellPermissionIdentity {
+ !locationManager.isLocationEnabled()
+ }
+ } else {
+ callWithShellPermissionIdentity {
+ sensorPrivacyManager.isSensorPrivacyEnabled(sensor)
+ }
+ }
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/StartForFutureActivity.kt b/tests/cts/permissionui/src/android/permissionui/cts/StartForFutureActivity.kt
new file mode 100644
index 000000000..643c01317
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/StartForFutureActivity.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 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.permissionui.cts
+
+import android.app.Activity
+import android.app.Instrumentation
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import java.util.concurrent.CompletableFuture
+
+class StartForFutureActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if (savedInstanceState != null) {
+ Log.w(TAG, "Activity was recreated. (Perhaps due to a configuration change?)")
+ }
+ }
+
+ fun startActivityForFuture(
+ intent: Intent,
+ future: CompletableFuture<Instrumentation.ActivityResult>
+ ) {
+ if (StartForFutureActivity.future != null) {
+ throw RuntimeException("StartForFutureActivity only supports launching one " +
+ "concurrent activity, but more than one was attempted.")
+ }
+
+ startActivityForResult(intent, 1)
+ StartForFutureActivity.future = future
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ future!!.complete(Instrumentation.ActivityResult(resultCode, data))
+ future = null
+ finish()
+ }
+
+ companion object {
+ private var future: CompletableFuture<Instrumentation.ActivityResult>? = null
+ private val TAG = StartForFutureActivity::class.simpleName
+ }
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/TestInstallerActivity.kt b/tests/cts/permissionui/src/android/permissionui/cts/TestInstallerActivity.kt
new file mode 100644
index 000000000..bae332a3c
--- /dev/null
+++ b/tests/cts/permissionui/src/android/permissionui/cts/TestInstallerActivity.kt
@@ -0,0 +1,21 @@
+/*
+ * 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.permissionui.cts
+
+import android.app.Activity
+
+class TestInstallerActivity : Activity()
diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp
new file mode 100644
index 000000000..db05067e4
--- /dev/null
+++ b/tests/cts/role/Android.bp
@@ -0,0 +1,49 @@
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "CtsRoleTestCases",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "30",
+
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+
+ static_libs: [
+ "androidx.test.rules",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "truth-prebuilt",
+ "platform-test-annotations",
+ ],
+
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-permission",
+ ],
+
+ data: [
+ ":CtsRoleTestApp",
+ ":CtsRoleTestApp28",
+ ":CtsRoleTestApp33WithoutInCallService",
+ ],
+}
diff --git a/tests/cts/role/AndroidManifest.xml b/tests/cts/role/AndroidManifest.xml
new file mode 100644
index 000000000..a8c8c8e3d
--- /dev/null
+++ b/tests/cts/role/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.role.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
+ <application>
+
+ <uses-library android:name="android.test.runner" />
+
+ <activity
+ android:name=".WaitForResultActivity"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"/>
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.app.role.cts"
+ android:label="CTS tests of android.app.role">
+ </instrumentation>
+</manifest>
diff --git a/tests/cts/role/AndroidTest.xml b/tests/cts/role/AndroidTest.xml
new file mode 100644
index 000000000..527ac3d32
--- /dev/null
+++ b/tests/cts/role/AndroidTest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<configuration description="Config for CTS role test cases">
+
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="permissions" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="run_on_sdk_sandbox" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" />
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk30ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsRoleTestCases.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts-role" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts-role"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="CtsRoleTestApp.apk->/data/local/tmp/cts-role/CtsRoleTestApp.apk" />
+ <option name="push" value="CtsRoleTestApp28.apk->/data/local/tmp/cts-role/CtsRoleTestApp28.apk" />
+ <option name="push" value="CtsRoleTestApp33WithoutInCallService.apk->/data/local/tmp/cts-role/CtsRoleTestApp33WithoutInCallService.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.app.role.cts" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+</configuration>
diff --git a/tests/cts/role/CtsRoleTestApp/Android.bp b/tests/cts/role/CtsRoleTestApp/Android.bp
new file mode 100644
index 000000000..1270e490b
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2018 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRoleTestApp",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.java"
+ ],
+}
diff --git a/tests/cts/role/CtsRoleTestApp/AndroidManifest.xml b/tests/cts/role/CtsRoleTestApp/AndroidManifest.xml
new file mode 100644
index 000000000..b2dfca961
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/AndroidManifest.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.role.cts.app">
+
+ <uses-permission android:name="android.permission.SEND_SMS" />
+
+ <application android:label="CtsRoleTestApp">
+
+ <activity
+ android:name=".RequestRoleActivity"
+ android:exported="true" />
+
+ <activity
+ android:name=".IsRoleHeldActivity"
+ android:exported="true" />
+
+ <activity
+ android:name=".ChangeDefaultDialerActivity"
+ android:exported="true" />
+
+ <activity
+ android:name=".ChangeDefaultSmsActivity"
+ android:exported="true" />
+
+ <!-- Dialer -->
+ <activity
+ android:name=".DialerDialActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="tel" />
+ </intent-filter>
+ </activity>
+ <service
+ android:name=".DialerInCallService"
+ android:permission="android.permission.BIND_INCALL_SERVICE"
+ android:exported="true">
+ <meta-data
+ android:name="android.telecom.IN_CALL_SERVICE_UI"
+ android:value="true"/>
+ <meta-data
+ android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI"
+ android:value="false"/>
+ <intent-filter>
+ <action android:name="android.telecom.InCallService" />
+ </intent-filter>
+ </service>
+ <!-- Sms -->
+ <activity
+ android:name=".SmsSendToActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.SENDTO" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="smsto" />
+ </intent-filter>
+ </activity>
+ <service
+ android:name=".SmsRespondViaMessageService"
+ android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="smsto" />
+ </intent-filter>
+ </service>
+ <receiver
+ android:name=".SmsDelieverReceiver"
+ android:permission="android.permission.BROADCAST_SMS"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.provider.Telephony.SMS_DELIVER" />
+ </intent-filter>
+ </receiver>
+ <receiver
+ android:name=".SmsWapPushDelieverReceiver"
+ android:permission="android.permission.BROADCAST_WAP_PUSH"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
+ <data android:mimeType="application/vnd.wap.mms-message" />
+ </intent-filter>
+ </receiver>
+
+ <!-- Browser -->
+ <activity
+ android:name=".BrowserActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="http" />
+ </intent-filter>
+ </activity>
+
+ <!-- Assistant -->
+ <activity
+ android:name=".AssistantActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.ASSIST" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultDialerActivity.java b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultDialerActivity.java
new file mode 100644
index 000000000..89cafa001
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultDialerActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.app.role.cts.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.telecom.TelecomManager;
+
+/**
+ * An activity that tries to change the default dialer app.
+ */
+public class ChangeDefaultDialerActivity extends Activity {
+
+ private static final int REQUEST_CODE_CHANGE_DEFAULT_DIALER = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
+ .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName);
+ startActivityForResult(intent, REQUEST_CODE_CHANGE_DEFAULT_DIALER);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CHANGE_DEFAULT_DIALER) {
+ setResult(resultCode, data);
+ finish();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultSmsActivity.java b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultSmsActivity.java
new file mode 100644
index 000000000..00559bf44
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/ChangeDefaultSmsActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 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.app.role.cts.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Telephony;
+
+/**
+ * An activity that tries to change the default SMS app.
+ */
+public class ChangeDefaultSmsActivity extends Activity {
+
+ private static final int REQUEST_CODE_CHANGE_DEFAULT_SMS = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
+ .putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName);
+ startActivityForResult(intent, REQUEST_CODE_CHANGE_DEFAULT_SMS);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_CHANGE_DEFAULT_SMS) {
+ setResult(resultCode, data);
+ finish();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/IsRoleHeldActivity.java b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/IsRoleHeldActivity.java
new file mode 100644
index 000000000..8e97f9f24
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/IsRoleHeldActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 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.app.role.cts.app;
+
+import android.app.Activity;
+import android.app.role.RoleManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+/**
+ * An activity that checks whether a role is held.
+ */
+public class IsRoleHeldActivity extends Activity {
+
+ private static final String EXTRA_IS_ROLE_HELD = "android.app.role.cts.app.extra.IS_ROLE_HELD";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ String roleName = getIntent().getStringExtra(Intent.EXTRA_ROLE_NAME);
+ if (TextUtils.isEmpty(roleName)) {
+ throw new IllegalArgumentException("Role name in extras cannot be null or empty");
+ }
+
+ RoleManager roleManager = getSystemService(RoleManager.class);
+ setResult(RESULT_OK, new Intent()
+ .putExtra(EXTRA_IS_ROLE_HELD, roleManager.isRoleHeld(roleName)));
+ finish();
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/RequestRoleActivity.java b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/RequestRoleActivity.java
new file mode 100644
index 000000000..b2d69e044
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp/src/android/app/role/cts/app/RequestRoleActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 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.app.role.cts.app;
+
+import android.app.Activity;
+import android.app.role.RoleManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+/**
+ * An activity that requests a role.
+ */
+public class RequestRoleActivity extends Activity {
+
+ private static final int REQUEST_CODE_REQUEST_ROLE = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String roleName = getIntent().getStringExtra(Intent.EXTRA_ROLE_NAME);
+ RoleManager roleManager = getSystemService(RoleManager.class);
+ Intent intent = roleManager.createRequestRoleIntent(roleName);
+ startActivityForResult(intent, REQUEST_CODE_REQUEST_ROLE);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_REQUEST_ROLE) {
+ setResult(resultCode, data);
+ finish();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp28/Android.bp b/tests/cts/role/CtsRoleTestApp28/Android.bp
new file mode 100644
index 000000000..dc8239edb
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp28/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2019 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRoleTestApp28",
+ min_sdk_version: "28",
+ target_sdk_version: "28",
+
+ srcs: [
+ "src/**/*.java"
+ ],
+}
diff --git a/tests/cts/role/CtsRoleTestApp28/AndroidManifest.xml b/tests/cts/role/CtsRoleTestApp28/AndroidManifest.xml
new file mode 100644
index 000000000..8113b2676
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp28/AndroidManifest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.role.cts.app28">
+
+ <uses-permission android:name="android.permission.SEND_SMS"/>
+
+ <application android:label="CtsRoleTestApp28">
+
+ <activity android:name=".ChangeDefaultDialerActivity"
+ android:exported="true"/>
+
+ <activity android:name=".ChangeDefaultSmsActivity"
+ android:exported="true"/>
+
+ <!-- Dialer -->
+ <activity android:name=".DialerDialActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <data android:scheme="tel"/>
+ </intent-filter>
+ </activity>
+
+ <!-- Sms -->
+ <activity android:name=".SmsSendToActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.SENDTO"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <data android:scheme="smsto"/>
+ </intent-filter>
+ </activity>
+ <service android:name=".SmsRespondViaMessageService"
+ android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <data android:scheme="smsto"/>
+ </intent-filter>
+ </service>
+ <receiver android:name=".SmsDelieverReceiver"
+ android:permission="android.permission.BROADCAST_SMS"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.provider.Telephony.SMS_DELIVER"/>
+ </intent-filter>
+ </receiver>
+ <receiver android:name=".SmsWapPushDelieverReceiver"
+ android:permission="android.permission.BROADCAST_WAP_PUSH"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/>
+ <data android:mimeType="application/vnd.wap.mms-message"/>
+ </intent-filter>
+ </receiver>
+ </application>
+</manifest>
diff --git a/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultDialerActivity.java b/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultDialerActivity.java
new file mode 100644
index 000000000..5d1c47cfc
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultDialerActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 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.app.role.cts.app28;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.telecom.TelecomManager;
+
+/**
+ * An activity that tries to change the default dialer app.
+ */
+public class ChangeDefaultDialerActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
+ .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName);
+ startActivity(intent);
+ }
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultSmsActivity.java b/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultSmsActivity.java
new file mode 100644
index 000000000..37819bbec
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp28/src/android/app/role/cts/app28/ChangeDefaultSmsActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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.app.role.cts.app28;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.Telephony;
+import android.telecom.TelecomManager;
+
+/**
+ * An activity that tries to change the default SMS app.
+ */
+public class ChangeDefaultSmsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
+ .putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName);
+ startActivity(intent);
+ }
+ }
+}
diff --git a/tests/cts/role/CtsRoleTestApp33WithoutInCallService/Android.bp b/tests/cts/role/CtsRoleTestApp33WithoutInCallService/Android.bp
new file mode 100644
index 000000000..7cce565af
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp33WithoutInCallService/Android.bp
@@ -0,0 +1,23 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRoleTestApp33WithoutInCallService",
+ min_sdk_version: "30",
+ target_sdk_version: "33",
+}
diff --git a/tests/cts/role/CtsRoleTestApp33WithoutInCallService/AndroidManifest.xml b/tests/cts/role/CtsRoleTestApp33WithoutInCallService/AndroidManifest.xml
new file mode 100644
index 000000000..a6504adae
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestApp33WithoutInCallService/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.role.cts.app33WithoutInCallService">
+ <application android:label="CtsRoleTestApp33WithoutInCallService">
+ <!-- Dialer -->
+ <activity
+ android:name=".DialerDialActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.DIAL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="tel" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/cts/role/OWNERS b/tests/cts/role/OWNERS
new file mode 100644
index 000000000..fb6099cf7
--- /dev/null
+++ b/tests/cts/role/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137825
+
+include platform/frameworks/base:/core/java/android/permission/OWNERS
diff --git a/tests/cts/role/TEST_MAPPING b/tests/cts/role/TEST_MAPPING
new file mode 100644
index 000000000..01d04bea0
--- /dev/null
+++ b/tests/cts/role/TEST_MAPPING
@@ -0,0 +1,48 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsRoleTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "mainline-presubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsRoleTestCases"
+ }
+ ],
+ "mainline-postsubmit": [
+ {
+ "name": "CtsRoleTestCases[com.google.android.permission.apex]",
+ "options": [
+ // TODO(b/238677748): These two tests currently fails on R base image
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#openDefaultAppListThenIsNotDefaultAppInList"
+ },
+ {
+ "exclude-filter": "android.app.role.cts.RoleManagerTest#removeSmsRoleHolderThenPermissionIsRevoked"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/cts/role/src/android/app/role/cts/RoleControllerManagerTest.kt b/tests/cts/role/src/android/app/role/cts/RoleControllerManagerTest.kt
new file mode 100644
index 000000000..0961b2680
--- /dev/null
+++ b/tests/cts/role/src/android/app/role/cts/RoleControllerManagerTest.kt
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2020 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.app.role.cts
+
+import android.app.Instrumentation
+
+import android.app.role.RoleManager
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Process
+import android.provider.Settings
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SdkSuppress
+import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.ThrowingSupplier
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import java.util.function.Consumer
+
+/**
+ * Tests RoleControllerManager APIs exposed on [RoleManager].
+ */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+class RoleControllerManagerTest {
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context: Context = instrumentation.context
+ private val packageManager: PackageManager = context.packageManager
+ private val roleManager: RoleManager = context.getSystemService(RoleManager::class.java)!!
+
+ @Before
+ fun installApp() {
+ installPackage(APP_APK_PATH)
+ }
+
+ @After
+ fun uninstallApp() {
+ uninstallPackage(APP_PACKAGE_NAME)
+ }
+
+ @Test
+ fun appIsVisibleForRole() {
+ assumeRoleIsVisible()
+ assertAppIsVisibleForRole(APP_PACKAGE_NAME, ROLE_NAME, true)
+ }
+
+ @Test
+ fun settingsIsNotVisibleForHomeRole() {
+ // Settings should never show as a possible home app even if qualified.
+ val settingsPackageName = packageManager.resolveActivity(
+ Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+ or PackageManager.MATCH_DIRECT_BOOT_AWARE or PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ )!!.activityInfo.packageName
+ assertAppIsVisibleForRole(settingsPackageName, RoleManager.ROLE_HOME, false)
+ }
+
+ @Test
+ fun appIsNotVisibleForInvalidRole() {
+ assertAppIsVisibleForRole(APP_PACKAGE_NAME, "invalid", false)
+ }
+
+ @Test
+ fun invalidAppIsNotVisibleForRole() {
+ assertAppIsVisibleForRole("invalid", ROLE_NAME, false)
+ }
+
+ private fun assertAppIsVisibleForRole(
+ packageName: String,
+ roleName: String,
+ expectedIsVisible: Boolean
+ ) {
+ runWithShellPermissionIdentity {
+ val future = CompletableFuture<Boolean>()
+ roleManager.isApplicationVisibleForRole(
+ roleName, packageName, context.mainExecutor, Consumer { future.complete(it) }
+ )
+ val isVisible = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ assertThat(isVisible).isEqualTo(expectedIsVisible)
+ }
+ }
+
+ private fun assumeRoleIsVisible() {
+ assumeTrue(isRoleVisible(ROLE_NAME))
+ }
+
+ @Test
+ fun systemGalleryRoleIsNotVisible() {
+ // The system gallery role should always be hidden.
+ assertThat(isRoleVisible(SYSTEM_GALLERY_ROLE_NAME)).isEqualTo(false)
+ }
+
+ @Test
+ fun invalidRoleIsNotVisible() {
+ assertThat(isRoleVisible("invalid")).isEqualTo(false)
+ }
+
+ private fun isRoleVisible(roleName: String): Boolean =
+ runWithShellPermissionIdentity(ThrowingSupplier {
+ val future = CompletableFuture<Boolean>()
+ roleManager.isRoleVisible(
+ roleName, context.mainExecutor, Consumer { future.complete(it) }
+ )
+ future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+ })
+
+ private fun installPackage(apkPath: String) {
+ assertEquals(
+ "Success",
+ runShellCommandOrThrow(
+ "pm install -r --user ${Process.myUserHandle().identifier} $apkPath"
+ )
+ .trim()
+ )
+ }
+
+ private fun uninstallPackage(packageName: String) {
+ assertEquals(
+ "Success",
+ runShellCommand("pm uninstall --user ${Process.myUserHandle().identifier} $packageName")
+ .trim()
+ )
+ }
+
+ companion object {
+ private const val ROLE_NAME = RoleManager.ROLE_BROWSER
+ private const val APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk"
+ private const val APP_PACKAGE_NAME = "android.app.role.cts.app"
+ private const val SYSTEM_GALLERY_ROLE_NAME = "android.app.role.SYSTEM_GALLERY"
+ private const val TIMEOUT_MILLIS = 15 * 1000L
+ }
+}
diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
new file mode 100644
index 000000000..a7429ac99
--- /dev/null
+++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
@@ -0,0 +1,1227 @@
+/*
+ * Copyright (C) 2018 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.app.role.cts;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
+import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObjectOrNull;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.role.OnRoleHoldersChangedListener;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.provider.Telephony;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.DisableAnimationRule;
+import com.android.compatibility.common.util.FreezeRotationRule;
+import com.android.compatibility.common.util.TestUtils;
+import com.android.compatibility.common.util.ThrowingRunnable;
+import com.android.compatibility.common.util.UiAutomatorUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
+
+/**
+ * Tests {@link RoleManager}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class RoleManagerTest {
+
+ private static final long TIMEOUT_MILLIS = 15 * 1000;
+
+ private static final long UNEXPECTED_TIMEOUT_MILLIS = 1000;
+
+ private static final String ROLE_NAME = RoleManager.ROLE_BROWSER;
+ private static final String ROLE_SHORT_LABEL = "Browser app";
+
+ private static final String APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk";
+ private static final String APP_PACKAGE_NAME = "android.app.role.cts.app";
+ private static final String APP_LABEL = "CtsRoleTestApp";
+ private static final String APP_IS_ROLE_HELD_ACTIVITY_NAME = APP_PACKAGE_NAME
+ + ".IsRoleHeldActivity";
+ private static final String APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD = APP_PACKAGE_NAME
+ + ".extra.IS_ROLE_HELD";
+ private static final String APP_REQUEST_ROLE_ACTIVITY_NAME = APP_PACKAGE_NAME
+ + ".RequestRoleActivity";
+ private static final String APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_PACKAGE_NAME
+ + ".ChangeDefaultDialerActivity";
+ private static final String APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_PACKAGE_NAME
+ + ".ChangeDefaultSmsActivity";
+
+ private static final String APP_28_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp28.apk";
+ private static final String APP_28_PACKAGE_NAME = "android.app.role.cts.app28";
+ private static final String APP_28_LABEL = "CtsRoleTestApp28";
+ private static final String APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME = APP_28_PACKAGE_NAME
+ + ".ChangeDefaultDialerActivity";
+ private static final String APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME = APP_28_PACKAGE_NAME
+ + ".ChangeDefaultSmsActivity";
+
+ private static final String APP_33_WITHOUT_INCALLSERVICE_APK_PATH =
+ "/data/local/tmp/cts-role/CtsRoleTestApp33WithoutInCallService.apk";
+ private static final String APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME =
+ "android.app.role.cts.app33WithoutInCallService";
+
+ private static final String PERMISSION_MANAGE_ROLES_FROM_CONTROLLER =
+ "com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER";
+
+ private static final Instrumentation sInstrumentation =
+ InstrumentationRegistry.getInstrumentation();
+ private static final Context sContext = InstrumentationRegistry.getTargetContext();
+ private static final PackageManager sPackageManager = sContext.getPackageManager();
+ private static final RoleManager sRoleManager = sContext.getSystemService(RoleManager.class);
+ private static final boolean sIsWatch = sPackageManager.hasSystemFeature(
+ PackageManager.FEATURE_WATCH);
+
+ @Rule
+ public DisableAnimationRule mDisableAnimationRule = new DisableAnimationRule();
+
+ @Rule
+ public FreezeRotationRule mFreezeRotationRule = new FreezeRotationRule();
+
+ @Rule
+ public ActivityTestRule<WaitForResultActivity> mActivityRule =
+ new ActivityTestRule<>(WaitForResultActivity.class);
+
+ private String mRoleHolder;
+
+ @Before
+ public void saveRoleHolder() throws Exception {
+ List<String> roleHolders = getRoleHolders(ROLE_NAME);
+ mRoleHolder = !roleHolders.isEmpty() ? roleHolders.get(0) : null;
+
+ if (Objects.equals(mRoleHolder, APP_PACKAGE_NAME)) {
+ removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+ mRoleHolder = null;
+ }
+ }
+
+ @After
+ public void restoreRoleHolder() throws Exception {
+ removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ if (mRoleHolder != null) {
+ addRoleHolder(ROLE_NAME, mRoleHolder);
+ }
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+ }
+
+ @Before
+ public void installApp() throws Exception {
+ installPackage(APP_APK_PATH);
+ installPackage(APP_28_APK_PATH);
+ installPackage(APP_33_WITHOUT_INCALLSERVICE_APK_PATH);
+ }
+
+ @After
+ public void uninstallApp() throws Exception {
+ uninstallPackage(APP_PACKAGE_NAME);
+ uninstallPackage(APP_28_PACKAGE_NAME);
+ uninstallPackage(APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME);
+ }
+
+ @Before
+ public void wakeUpScreen() throws IOException {
+ runShellCommand(sInstrumentation, "input keyevent KEYCODE_WAKEUP");
+ }
+
+ @Before
+ public void closeNotificationShade() {
+ sContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ @Test
+ public void requestRoleIntentHasPermissionControllerPackage() throws Exception {
+ Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
+
+ assertThat(intent.getPackage()).isEqualTo(
+ sPackageManager.getPermissionControllerPackageName());
+ }
+
+ @Test
+ public void requestRoleIntentHasExtraRoleName() throws Exception {
+ Intent intent = sRoleManager.createRequestRoleIntent(ROLE_NAME);
+
+ assertThat(intent.getStringExtra(Intent.EXTRA_ROLE_NAME)).isEqualTo(ROLE_NAME);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestRoleAndDenyThenIsNotRoleHolder() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestRoleAndAllowThenIsRoleHolder() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(true);
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestRoleFirstTimeNoDontAskAgain() throws Exception {
+ requestRole(ROLE_NAME);
+ UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
+
+ assertThat(dontAskAgainCheck).isNull();
+
+ respondToRoleRequest(false);
+ }
+
+ @Test
+ @FlakyTest
+ public void requestRoleAndDenyThenHasDontAskAgain() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ requestRole(ROLE_NAME);
+ UiObject2 dontAskAgainCheck = findDontAskAgainCheck();
+
+ assertThat(dontAskAgainCheck).isNotNull();
+
+ respondToRoleRequest(false);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestRoleAndDenyWithDontAskAgainReturnsCanceled() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ requestRole(ROLE_NAME);
+ findDontAskAgainCheck().click();
+ Pair<Integer, Intent> result = clickButtonAndWaitForResult(true);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest
+ public void requestRoleAndDenyWithDontAskAgainThenDeniedAutomatically() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ requestRole(ROLE_NAME);
+ findDontAskAgainCheck().click();
+ clickButtonAndWaitForResult(true);
+
+ requestRole(ROLE_NAME);
+ Pair<Integer, Intent> result = waitForResult();
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest
+ public void requestRoleAndDenyWithDontAskAgainAndClearDataThenShowsUiWithoutDontAskAgain()
+ throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ requestRole(ROLE_NAME);
+ findDontAskAgainCheck().click();
+ clickButtonAndWaitForResult(true);
+ // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
+ // when the test app is force stopped, our task isn't force finished and our
+ // WaitForResultActivity can survive.
+ Thread.sleep(5000);
+
+ clearPackageData(APP_PACKAGE_NAME);
+ // Wait for the don't ask again to be forgotten.
+ Thread.sleep(10000);
+
+ TestUtils.waitUntil("Find and respond to request role UI", () -> {
+ requestRole(ROLE_NAME);
+ UiObject2 cancelButton = waitFindObjectOrNull(By.res("android:id/button2"));
+ if (cancelButton == null) {
+ // Dialog not found, try again later.
+ return false;
+ }
+ UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
+
+ assertThat(dontAskAgainCheck).isNull();
+
+ respondToRoleRequest(false);
+ return true;
+ });
+ }
+
+ @Test
+ @FlakyTest
+ public void requestRoleAndDenyWithDontAskAgainAndReinstallThenShowsUiWithoutDontAskAgain()
+ throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(false);
+
+ requestRole(ROLE_NAME);
+ findDontAskAgainCheck().click();
+ clickButtonAndWaitForResult(true);
+ // Wait for the RequestRoleActivity inside the test app to be removed from our task so that
+ // when the test app is uninstalled, our task isn't force finished and our
+ // WaitForResultActivity can survive.
+ Thread.sleep(5000);
+
+ uninstallPackage(APP_PACKAGE_NAME);
+ // Wait for the don't ask again to be forgotten.
+ Thread.sleep(10000);
+ installPackage(APP_APK_PATH);
+
+ TestUtils.waitUntil("Find and respond to request role UI", () -> {
+ requestRole(ROLE_NAME);
+ UiObject2 cancelButton = waitFindObjectOrNull(By.res("android:id/button2"));
+ if (cancelButton == null) {
+ // Dialog not found, try again later.
+ return false;
+ }
+ UiObject2 dontAskAgainCheck = findDontAskAgainCheck(false);
+
+ assertThat(dontAskAgainCheck).isNull();
+
+ respondToRoleRequest(false);
+ return true;
+ });
+ }
+
+ @Test
+ public void requestInvalidRoleThenDeniedAutomatically() throws Exception {
+ requestRole("invalid");
+ Pair<Integer, Intent> result = waitForResult();
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void requestUnqualifiedRoleThenDeniedAutomatically() throws Exception {
+ requestRole(RoleManager.ROLE_HOME);
+ Pair<Integer, Intent> result = waitForResult();
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void requestAssistantRoleThenDeniedAutomatically() throws Exception {
+ requestRole(RoleManager.ROLE_ASSISTANT);
+ Pair<Integer, Intent> result = waitForResult();
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestHoldingRoleThenAllowedAutomatically() throws Exception {
+ requestRole(ROLE_NAME);
+ respondToRoleRequest(true);
+
+ requestRole(ROLE_NAME);
+ Pair<Integer, Intent> result = waitForResult();
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_OK);
+ }
+
+ private void requestRole(@NonNull String roleName) {
+ Intent intent = new Intent()
+ .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_REQUEST_ROLE_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
+ mActivityRule.getActivity().startActivityToWaitForResult(intent);
+ }
+
+ private void respondToRoleRequest(boolean allow)
+ throws InterruptedException, UiObjectNotFoundException {
+ if (allow) {
+ waitFindObject(By.text(APP_LABEL)).click();
+ }
+ Pair<Integer, Intent> result = clickButtonAndWaitForResult(allow);
+ int expectedResult = allow ? Activity.RESULT_OK : Activity.RESULT_CANCELED;
+
+ assertThat(result.first).isEqualTo(expectedResult);
+ }
+
+ @Nullable
+ private UiObject2 findDontAskAgainCheck(boolean expected) throws UiObjectNotFoundException {
+ BySelector selector = By.res("com.android.permissioncontroller:id/dont_ask_again");
+ return expected
+ ? waitFindObject(selector)
+ : waitFindObjectOrNull(selector, UNEXPECTED_TIMEOUT_MILLIS);
+ }
+
+ @Nullable
+ private UiObject2 findDontAskAgainCheck() throws UiObjectNotFoundException {
+ return findDontAskAgainCheck(true);
+ }
+
+ @NonNull
+ private Pair<Integer, Intent> clickButtonAndWaitForResult(boolean positive)
+ throws InterruptedException, UiObjectNotFoundException {
+ waitFindObject(By.res(positive ? "android:id/button1" : "android:id/button2")).click();
+ return waitForResult();
+ }
+
+ @NonNull
+ private Pair<Integer, Intent> waitForResult() throws InterruptedException {
+ return mActivityRule.getActivity().waitForActivityResult(TIMEOUT_MILLIS);
+ }
+
+ private void clearPackageData(@NonNull String packageName) {
+ runShellCommand("pm clear --user " + Process.myUserHandle().getIdentifier() + " "
+ + packageName);
+ }
+
+ private void installPackage(@NonNull String apkPath) {
+ runShellCommandOrThrow(
+ "pm install -r --user " + Process.myUserHandle().getIdentifier() + " " + apkPath);
+ }
+
+ private void uninstallPackage(@NonNull String packageName) {
+ runShellCommand("pm uninstall --user " + Process.myUserHandle().getIdentifier() + " "
+ + packageName);
+ }
+
+ @Test
+ public void targetCurrentSdkAndChangeDefaultDialerThenDeniedAutomatically() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
+
+ WaitForResultActivity activity = mActivityRule.getActivity();
+ activity.startActivityToWaitForResult(new Intent()
+ .setComponent(new ComponentName(APP_PACKAGE_NAME,
+ APP_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
+ Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ public void targetCurrentSdkAndChangeDefaultSmsThenDeniedAutomatically() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ WaitForResultActivity activity = mActivityRule.getActivity();
+ activity.startActivityToWaitForResult(new Intent()
+ .setComponent(new ComponentName(APP_PACKAGE_NAME,
+ APP_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
+ Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void targetSdk28AndChangeDefaultDialerAndAllowThenIsDefaultDialer() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
+
+ sContext.startActivity(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ waitFindObject(By.text(APP_28_LABEL)).click();
+ waitFindObject(By.res("android:id/button1")).click();
+
+ // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
+ //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
+ //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
+ // telecomManager.getDefaultDialerPackage(), APP_28_PACKAGE_NAME));
+ TestUtils.waitUntil("App is not set as default dialer app", () ->
+ getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_28_PACKAGE_NAME));
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void targetSdk28AndChangeDefaultSmsAndAllowThenIsDefaultSms() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ sContext.startActivity(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_28_PACKAGE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ waitFindObject(By.text(APP_28_LABEL)).click();
+ waitFindObject(By.res("android:id/button1")).click();
+
+ TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
+ Telephony.Sms.getDefaultSmsPackage(sContext), APP_28_PACKAGE_NAME));
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void targetSdk28AndChangeDefaultDialerForAnotherAppThenDeniedAutomatically()
+ throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
+
+ WaitForResultActivity activity = mActivityRule.getActivity();
+ activity.startActivityToWaitForResult(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
+ Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void targetSdk28AndChangeDefaultSmsForAnotherAppThenDeniedAutomatically()
+ throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ WaitForResultActivity activity = mActivityRule.getActivity();
+ activity.startActivityToWaitForResult(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME));
+ Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_CANCELED);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void
+ targetSdk28AndChangeDefaultDialerForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultDialer()
+ throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
+
+ addRoleHolder(RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME);
+ sContext.startActivity(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_DIALER_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ waitFindObject(By.text(APP_LABEL)).click();
+ waitFindObject(By.res("android:id/button1")).click();
+
+ // TODO(b/149037075): Use TelecomManager.getDefaultDialerPackage() once the bug is fixed.
+ //TelecomManager telecomManager = sContext.getSystemService(TelecomManager.class);
+ //TestUtils.waitUntil("App is not set as default dialer app", () -> Objects.equals(
+ // telecomManager.getDefaultDialerPackage(), APP_PACKAGE_NAME));
+ TestUtils.waitUntil("App is not set as default dialer app", () ->
+ getRoleHolders(RoleManager.ROLE_DIALER).contains(APP_PACKAGE_NAME));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ public void testHoldDialerRoleRequirementWithInCallServiceAndSdk()
+ throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER));
+ // target below sdk 33 without InCallService component can hold dialer role
+ addRoleHolder(
+ RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME, true);
+ assertIsRoleHolder(
+ RoleManager.ROLE_DIALER, APP_28_PACKAGE_NAME, true);
+ // target sdk 33 without InCallService component cannot hold dialer role
+ addRoleHolder(
+ RoleManager.ROLE_DIALER, APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME, false);
+ assertIsRoleHolder(
+ RoleManager.ROLE_DIALER, APP_33_WITHOUT_INCALLSERVICE_PACKAGE_NAME, false);
+ // target sdk 33 with InCallService component can hold dialer role
+ addRoleHolder(
+ RoleManager.ROLE_DIALER, APP_PACKAGE_NAME, true);
+ assertIsRoleHolder(
+ RoleManager.ROLE_DIALER, APP_PACKAGE_NAME, true);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void
+ targetSdk28AndChangeDefaultSmsForAnotherAppAsHolderAndAllowThenTheOtherAppIsDefaultSms()
+ throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ addRoleHolder(RoleManager.ROLE_SMS, APP_28_PACKAGE_NAME);
+ sContext.startActivity(new Intent()
+ .setComponent(new ComponentName(APP_28_PACKAGE_NAME,
+ APP_28_CHANGE_DEFAULT_SMS_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ waitFindObject(By.text(APP_LABEL)).click();
+ waitFindObject(By.res("android:id/button1")).click();
+
+ TestUtils.waitUntil("App is not set as default sms app", () -> Objects.equals(
+ Telephony.Sms.getDefaultSmsPackage(sContext), APP_PACKAGE_NAME));
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppDetailsThenIsNotDefaultApp() throws Exception {
+ runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
+ Intent.ACTION_MANAGE_DEFAULT_APP)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
+
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+
+ pressBack();
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppDetailsAndSetDefaultAppThenIsDefaultApp() throws Exception {
+ runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
+ Intent.ACTION_MANAGE_DEFAULT_APP)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
+ waitForIdle();
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(
+ By.text(APP_LABEL))).click();
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL))).click();
+ }
+
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
+
+ pressBack();
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppDetailsAndSetDefaultAppAndSetAnotherThenIsNotDefaultApp()
+ throws Exception {
+ runWithShellPermissionIdentity(() -> sContext.startActivity(new Intent(
+ Intent.ACTION_MANAGE_DEFAULT_APP)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NAME)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK)));
+ waitForIdle();
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(
+ By.text(APP_LABEL))).click();
+ waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL))).click();
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+ waitForIdle();
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false)).click();
+ } else {
+ waitFindObject(
+ By.clickable(true).hasDescendant(By.checkable(true).checked(false))).click();
+ }
+
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+
+ pressBack();
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppListThenHasDefaultApp() throws Exception {
+ sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+
+ waitFindObject(By.text(ROLE_SHORT_LABEL));
+
+ pressBack();
+ }
+
+ @Test
+ public void openDefaultAppListThenIsNotDefaultAppInList() throws Exception {
+ sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+
+ assertThat(waitFindObjectOrNull(By.text(APP_LABEL), UNEXPECTED_TIMEOUT_MILLIS))
+ .isNull();
+
+ pressBack();
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppListAndSetDefaultAppThenIsDefaultApp() throws Exception {
+ sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+ waitForIdle();
+ waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
+ waitForIdle();
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(
+ By.text(APP_LABEL))).click();
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL))).click();
+ }
+
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
+
+ pressBack();
+ pressBack();
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList() throws Exception {
+ sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+ waitForIdle();
+ waitFindObject(By.text(ROLE_SHORT_LABEL)).click();
+ waitForIdle();
+ if (sIsWatch) {
+ waitFindObject(By.clickable(true).checked(false).hasDescendant(
+ By.text(APP_LABEL))).click();
+ waitFindObject(By.clickable(true).checked(true).hasDescendant(By.text(APP_LABEL)));
+ } else {
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL))).click();
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(true))
+ .hasDescendant(By.text(APP_LABEL)));
+ }
+ pressBack();
+
+ waitFindObject(By.text(APP_LABEL));
+
+ pressBack();
+ }
+
+ private static void waitForIdle() {
+ UiAutomatorUtils.getUiDevice().waitForIdle();
+ }
+
+ private static void pressBack() {
+ UiAutomatorUtils.getUiDevice().pressBack();
+ waitForIdle();
+ }
+
+ @Test
+ public void roleIsAvailable() {
+ assertThat(sRoleManager.isRoleAvailable(ROLE_NAME)).isTrue();
+ }
+
+ @Test
+ public void dontAddRoleHolderThenRoleIsNotHeld() throws Exception {
+ assertRoleIsHeld(ROLE_NAME, false);
+ }
+
+ @Test
+ public void addRoleHolderThenRoleIsHeld() throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertRoleIsHeld(ROLE_NAME, true);
+ }
+
+ @Test
+ public void addAndRemoveRoleHolderThenRoleIsNotHeld() throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+ removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertRoleIsHeld(ROLE_NAME, false);
+ }
+
+ private void assertRoleIsHeld(@NonNull String roleName, boolean isHeld)
+ throws InterruptedException {
+ Intent intent = new Intent()
+ .setComponent(new ComponentName(APP_PACKAGE_NAME, APP_IS_ROLE_HELD_ACTIVITY_NAME))
+ .putExtra(Intent.EXTRA_ROLE_NAME, roleName);
+ WaitForResultActivity activity = mActivityRule.getActivity();
+ activity.startActivityToWaitForResult(intent);
+ Pair<Integer, Intent> result = activity.waitForActivityResult(TIMEOUT_MILLIS);
+
+ assertThat(result.first).isEqualTo(Activity.RESULT_OK);
+ assertThat(result.second).isNotNull();
+ assertThat(result.second.hasExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD)).isTrue();
+ assertThat(result.second.getBooleanExtra(APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD, false))
+ .isEqualTo(isHeld);
+ }
+
+ @Test
+ public void dontAddRoleHolderThenIsNotRoleHolder() throws Exception {
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void addRoleHolderThenIsRoleHolder() throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
+ }
+
+ @Test
+ public void addAndRemoveRoleHolderThenIsNotRoleHolder() throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+ removeRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void addAndClearRoleHoldersThenIsNotRoleHolder() throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+ clearRoleHolders(ROLE_NAME);
+
+ assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void addInvalidRoleHolderThenFails() throws Exception {
+ addRoleHolder("invalid", APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void addUnqualifiedRoleHolderThenFails() throws Exception {
+ addRoleHolder(RoleManager.ROLE_HOME, APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void removeInvalidRoleHolderThenFails() throws Exception {
+ removeRoleHolder("invalid", APP_PACKAGE_NAME, false);
+ }
+
+ @Test
+ public void clearInvalidRoleHoldersThenFails() throws Exception {
+ clearRoleHolders("invalid", false);
+ }
+
+ @Test
+ public void addOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotified() throws Exception {
+ assertOnRoleHoldersChangedListenerIsNotified(() -> addRoleHolder(ROLE_NAME,
+ APP_PACKAGE_NAME));
+ }
+
+ @Test
+ public void addOnRoleHoldersChangedListenerAndRemoveRoleHolderThenIsNotified()
+ throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertOnRoleHoldersChangedListenerIsNotified(() -> removeRoleHolder(ROLE_NAME,
+ APP_PACKAGE_NAME));
+ }
+
+ @Test
+ public void addOnRoleHoldersChangedListenerAndClearRoleHoldersThenIsNotified()
+ throws Exception {
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ assertOnRoleHoldersChangedListenerIsNotified(() -> clearRoleHolders(ROLE_NAME));
+ }
+
+ private void assertOnRoleHoldersChangedListenerIsNotified(@NonNull ThrowingRunnable runnable)
+ throws Exception {
+ ListenerFuture future = new ListenerFuture();
+ UserHandle user = Process.myUserHandle();
+ runWithShellPermissionIdentity(() -> sRoleManager.addOnRoleHoldersChangedListenerAsUser(
+ sContext.getMainExecutor(), future, user));
+ Pair<String, UserHandle> result;
+ try {
+ runnable.run();
+ result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } finally {
+ runWithShellPermissionIdentity(() ->
+ sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user));
+ }
+
+ assertThat(result.first).isEqualTo(ROLE_NAME);
+ assertThat(result.second).isEqualTo(user);
+ }
+
+ @Test
+ public void addAndRemoveOnRoleHoldersChangedListenerAndAddRoleHolderThenIsNotNotified()
+ throws Exception {
+ ListenerFuture future = new ListenerFuture();
+ UserHandle user = Process.myUserHandle();
+ runWithShellPermissionIdentity(() -> {
+ sRoleManager.addOnRoleHoldersChangedListenerAsUser(sContext.getMainExecutor(), future,
+ user);
+ sRoleManager.removeOnRoleHoldersChangedListenerAsUser(future, user);
+ });
+ addRoleHolder(ROLE_NAME, APP_PACKAGE_NAME);
+
+ try {
+ future.get(UNEXPECTED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ // Expected
+ return;
+ }
+ throw new AssertionError("OnRoleHoldersChangedListener was notified after removal");
+ }
+
+ @Test
+ public void setRoleNamesFromControllerShouldRequireManageRolesFromControllerPermission() {
+ assertRequiresManageRolesFromControllerPermission(
+ () -> sRoleManager.setRoleNamesFromController(Collections.emptyList()),
+ "setRoleNamesFromController");
+ }
+
+ @Test
+ public void addRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
+ assertRequiresManageRolesFromControllerPermission(
+ () -> sRoleManager.addRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
+ "addRoleHolderFromController");
+ }
+
+ @Test
+ public void removeRoleHolderFromControllerShouldRequireManageRolesFromControllerPermission() {
+ assertRequiresManageRolesFromControllerPermission(
+ () -> sRoleManager.removeRoleHolderFromController(ROLE_NAME, APP_PACKAGE_NAME),
+ "removeRoleHolderFromController");
+ }
+
+ @Test
+ public void getHeldRolesFromControllerShouldRequireManageRolesFromControllerPermission() {
+ assertRequiresManageRolesFromControllerPermission(
+ () -> sRoleManager.getHeldRolesFromController(APP_PACKAGE_NAME),
+ "getHeldRolesFromController");
+ }
+
+ private void assertRequiresManageRolesFromControllerPermission(@NonNull Runnable runnable,
+ @NonNull String methodName) {
+ try {
+ runnable.run();
+ } catch (SecurityException e) {
+ if (e.getMessage().contains(PERMISSION_MANAGE_ROLES_FROM_CONTROLLER)) {
+ // Expected
+ return;
+ }
+ throw e;
+ }
+ fail("RoleManager." + methodName + "() should require "
+ + PERMISSION_MANAGE_ROLES_FROM_CONTROLLER);
+ }
+
+ @Test
+ public void manageRolesFromControllerPermissionShouldBeDeclaredByPermissionController()
+ throws PackageManager.NameNotFoundException {
+ PermissionInfo permissionInfo = sPackageManager.getPermissionInfo(
+ PERMISSION_MANAGE_ROLES_FROM_CONTROLLER, 0);
+
+ assertThat(permissionInfo.packageName).isEqualTo(
+ sPackageManager.getPermissionControllerPackageName());
+ assertThat(permissionInfo.getProtection()).isEqualTo(PermissionInfo.PROTECTION_SIGNATURE);
+ assertThat(permissionInfo.getProtectionFlags()).isEqualTo(0);
+ }
+
+ @Test
+ public void smsRoleHasHolder() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ assertThat(getRoleHolders(RoleManager.ROLE_SMS)).isNotEmpty();
+ }
+
+ @Test
+ public void addSmsRoleHolderThenPermissionIsGranted() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
+
+ assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
+ APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
+ }
+
+ @Test
+ public void removeSmsRoleHolderThenPermissionIsRevoked() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
+ addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
+ addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
+
+ assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
+ APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_DENIED);
+ }
+
+ @Test
+ public void removeSmsRoleHolderThenDialerRolePermissionIsRetained() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_DIALER)
+ && sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ addRoleHolder(RoleManager.ROLE_DIALER, APP_PACKAGE_NAME);
+ String smsRoleHolder = getRoleHolders(RoleManager.ROLE_SMS).get(0);
+ addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
+ addRoleHolder(RoleManager.ROLE_SMS, smsRoleHolder);
+
+ assertThat(sPackageManager.checkPermission(android.Manifest.permission.SEND_SMS,
+ APP_PACKAGE_NAME)).isEqualTo(PackageManager.PERMISSION_GRANTED);
+ }
+
+ @Test
+ public void packageManagerGetDefaultBrowserBackedByRole() throws Exception {
+ addRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME);
+
+ assertThat(sPackageManager.getDefaultBrowserPackageNameAsUser(UserHandle.myUserId()))
+ .isEqualTo(APP_PACKAGE_NAME);
+ }
+
+ @Test
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void packageManagerSetDefaultBrowserBackedByRole() throws Exception {
+ callWithShellPermissionIdentity(() -> sPackageManager.setDefaultBrowserPackageNameAsUser(
+ APP_PACKAGE_NAME, UserHandle.myUserId()));
+
+ assertIsRoleHolder(RoleManager.ROLE_BROWSER, APP_PACKAGE_NAME, true);
+ }
+
+ @Test
+ public void telephonySmsGetDefaultSmsPackageBackedByRole() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
+
+ assertThat(Telephony.Sms.getDefaultSmsPackage(sContext)).isEqualTo(APP_PACKAGE_NAME);
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+ @Test
+ public void cannotBypassRoleQualificationWithoutPermission() throws Exception {
+ assertThrows(SecurityException.class, () ->
+ sRoleManager.setBypassingRoleQualification(true));
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+ @Test
+ public void bypassRoleQualificationThenCanAddUnqualifiedRoleHolder() throws Exception {
+ assertThat(sRoleManager.isRoleAvailable(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
+ .isTrue();
+
+ runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(true));
+ try {
+ assertThat(callWithShellPermissionIdentity(() ->
+ sRoleManager.isBypassingRoleQualification())).isTrue();
+
+ // The System Activity Recognizer role requires a system app, so this won't succeed
+ // without bypassing role qualification.
+ addRoleHolder(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, APP_PACKAGE_NAME);
+
+ assertThat(getRoleHolders(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER))
+ .contains(APP_PACKAGE_NAME);
+ } finally {
+ runWithShellPermissionIdentity(() -> sRoleManager.setBypassingRoleQualification(false));
+ }
+ assertThat(callWithShellPermissionIdentity(() ->
+ sRoleManager.isBypassingRoleQualification())).isFalse();
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void cannotGetDefaultApplicationWithoutPermission() throws Exception {
+ assertThrows(SecurityException.class, ()->
+ sRoleManager.getDefaultApplication(
+ RoleManager.ROLE_SMS));
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void getDefaultApplicationChecksRoles() throws Exception {
+ runWithShellPermissionIdentity(() ->
+ assertThrows(IllegalArgumentException.class, () ->
+ sRoleManager.getDefaultApplication(
+ RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER)));
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void getDefaultApplicationReadsRole() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ addRoleHolder(RoleManager.ROLE_SMS, APP_PACKAGE_NAME);
+ runWithShellPermissionIdentity(() -> {
+ assertThat(sRoleManager.getDefaultApplication(RoleManager.ROLE_SMS))
+ .isEqualTo(APP_PACKAGE_NAME);
+ });
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void cannotSetDefaultApplicationWithoutPermission() throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ assertThrows(SecurityException.class, ()->
+ sRoleManager.setDefaultApplication(
+ RoleManager.ROLE_SMS, APP_PACKAGE_NAME, 0,
+ sContext.getMainExecutor(), future));
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void setDefaultApplicationChecksRoles() throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() ->
+ assertThrows(IllegalArgumentException.class, () ->
+ sRoleManager.setDefaultApplication(
+ RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, APP_PACKAGE_NAME, 0,
+ sContext.getMainExecutor(), future)));
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @Test
+ public void setDefaultApplicationSetsRole() throws Exception {
+ assumeTrue(sRoleManager.isRoleAvailable(RoleManager.ROLE_SMS));
+
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() -> {
+ sRoleManager.setDefaultApplication(
+ RoleManager.ROLE_SMS, APP_PACKAGE_NAME, 0,
+ sContext.getMainExecutor(), future);
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue();
+ assertThat(sRoleManager.getRoleHolders(RoleManager.ROLE_SMS))
+ .containsExactly(APP_PACKAGE_NAME);
+ });
+ }
+
+ @NonNull
+ private List<String> getRoleHolders(@NonNull String roleName) throws Exception {
+ return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));
+ }
+
+ private void assertIsRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ boolean shouldBeRoleHolder) throws Exception {
+ List<String> packageNames = getRoleHolders(roleName);
+
+ if (shouldBeRoleHolder) {
+ assertThat(packageNames).contains(packageName);
+ } else {
+ assertThat(packageNames).doesNotContain(packageName);
+ }
+ }
+
+ private void addRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ boolean expectSuccess) throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() -> sRoleManager.addRoleHolderAsUser(roleName,
+ packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
+ }
+
+ private void addRoleHolder(@NonNull String roleName, @NonNull String packageName)
+ throws Exception {
+ addRoleHolder(roleName, packageName, true);
+ }
+
+ private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName,
+ boolean expectSuccess) throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() -> sRoleManager.removeRoleHolderAsUser(roleName,
+ packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
+ }
+
+ private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName)
+ throws Exception {
+ removeRoleHolder(roleName, packageName, true);
+ }
+
+ private void clearRoleHolders(@NonNull String roleName, boolean expectSuccess)
+ throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() -> sRoleManager.clearRoleHoldersAsUser(roleName, 0,
+ Process.myUserHandle(), sContext.getMainExecutor(), future));
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
+ }
+
+ private void clearRoleHolders(@NonNull String roleName) throws Exception {
+ clearRoleHolders(roleName, true);
+ }
+
+ private static class ListenerFuture extends CompletableFuture<Pair<String, UserHandle>>
+ implements OnRoleHoldersChangedListener {
+
+ @Override
+ public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
+ complete(new Pair<>(roleName, user));
+ }
+ }
+
+ private static class CallbackFuture extends CompletableFuture<Boolean>
+ implements Consumer<Boolean> {
+
+ @Override
+ public void accept(Boolean successful) {
+ complete(successful);
+ }
+ }
+}
diff --git a/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt b/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt
new file mode 100644
index 000000000..d9322ec21
--- /dev/null
+++ b/tests/cts/role/src/android/app/role/cts/RoleShellCommandTest.kt
@@ -0,0 +1,202 @@
+/*
+ * 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.app.role.cts
+
+import android.app.role.RoleManager
+import android.os.Build
+import android.os.UserHandle
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SdkSuppress
+import androidx.test.runner.AndroidJUnit4
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Assert.assertThrows
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Tests role shell commands.
+ */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
+class RoleShellCommandTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.context
+ private val roleManager = context.getSystemService(RoleManager::class.java)!!
+ private val userId = UserHandle.myUserId()
+
+ private var roleHolder: String? = null
+ private var wasBypassingRoleQualification: Boolean = false
+
+ @Before
+ fun saveRoleHolder() {
+ roleHolder = getRoleHolders().firstOrNull()
+ if (roleHolder == APP_PACKAGE_NAME) {
+ removeRoleHolder()
+ roleHolder = null
+ }
+ }
+
+ @Before
+ fun saveBypassingRoleQualification() {
+ wasBypassingRoleQualification = isBypassingRoleQualification()
+ }
+
+ @After
+ fun restoreRoleHolder() {
+ removeRoleHolder()
+ roleHolder?.let { addRoleHolder(it) }
+ assertIsRoleHolder(false)
+ }
+
+ @After
+ fun restoreBypassingRoleQualification() {
+ setBypassingRoleQualification(wasBypassingRoleQualification)
+ }
+
+ @Before
+ fun installApp() {
+ installPackage(APP_APK_PATH)
+ }
+
+ @After
+ fun uninstallApp() {
+ uninstallPackage(APP_PACKAGE_NAME)
+ }
+
+ @Test
+ fun helpPrintsNonEmpty() {
+ assertThat(runShellCommandOrThrow("cmd role help")).isNotEmpty()
+ }
+
+ @Test
+ fun dontAddRoleHolderThenIsNotRoleHolder() {
+ assertIsRoleHolder(false)
+ }
+
+ @Test
+ fun addRoleHolderThenIsRoleHolder() {
+ addRoleHolder()
+
+ assertIsRoleHolder(true)
+ }
+
+ @Test
+ fun addAndRemoveRoleHolderThenIsNotRoleHolder() {
+ addRoleHolder()
+ removeRoleHolder()
+
+ assertIsRoleHolder(false)
+ }
+
+ @Test
+ fun addAndClearRoleHolderThenIsNotRoleHolder() {
+ addRoleHolder()
+ clearRoleHolders()
+
+ assertIsRoleHolder(false)
+ }
+
+ @Test
+ fun addInvalidRoleHolderThenFails() {
+ assertThrows(AssertionError::class.java) {
+ runShellCommandOrThrow("cmd role add-role-holder --user $userId $ROLE_NAME invalid")
+ }
+ }
+
+ @Test
+ fun addRoleHolderThenAppearsInDumpsys() {
+ addRoleHolder()
+
+ assertThat(runShellCommandOrThrow("dumpsys role")).contains(APP_PACKAGE_NAME)
+ }
+
+ @Test
+ fun setBypassingRoleQualificationToTrueThenSetsToTrue() {
+ setBypassingRoleQualification(false)
+
+ runShellCommandOrThrow("cmd role set-bypassing-role-qualification true")
+
+ assertThat(isBypassingRoleQualification()).isTrue()
+ }
+
+ @Test
+ fun setBypassingRoleQualificationToFalseThenSetsToFalse() {
+ setBypassingRoleQualification(true)
+
+ runShellCommandOrThrow("cmd role set-bypassing-role-qualification false")
+
+ assertThat(isBypassingRoleQualification()).isFalse()
+ }
+
+ private fun addRoleHolder(packageName: String = APP_PACKAGE_NAME) {
+ runShellCommandOrThrow("cmd role add-role-holder --user $userId $ROLE_NAME $packageName")
+ }
+
+ private fun removeRoleHolder(packageName: String = APP_PACKAGE_NAME) {
+ runShellCommandOrThrow("cmd role remove-role-holder --user $userId $ROLE_NAME $packageName")
+ }
+
+ private fun clearRoleHolders() {
+ runShellCommandOrThrow("cmd role clear-role-holders --user $userId $ROLE_NAME")
+ }
+
+ private fun getRoleHolders(): List<String> =
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ runShellCommandOrThrow("cmd role get-role-holders --user $userId $ROLE_NAME")
+ .trim().let { if (it.isNotEmpty()) it.split(";") else emptyList() }
+ } else {
+ callWithShellPermissionIdentity { roleManager.getRoleHolders(ROLE_NAME) }
+ }
+
+ private fun assertIsRoleHolder(shouldBeRoleHolder: Boolean) {
+ val packageNames = getRoleHolders()
+ if (shouldBeRoleHolder) {
+ assertThat(packageNames).contains(APP_PACKAGE_NAME)
+ } else {
+ assertThat(packageNames).doesNotContain(APP_PACKAGE_NAME)
+ }
+ }
+
+ private fun installPackage(apkPath: String) {
+ assertThat(runShellCommandOrThrow("pm install -r --user $userId $apkPath").trim())
+ .isEqualTo("Success")
+ }
+
+ private fun uninstallPackage(packageName: String) {
+ assertThat(runShellCommandOrThrow("pm uninstall --user $userId $packageName").trim())
+ .isEqualTo("Success")
+ }
+
+ private fun isBypassingRoleQualification(): Boolean =
+ callWithShellPermissionIdentity { roleManager.isBypassingRoleQualification() }
+
+ private fun setBypassingRoleQualification(value: Boolean) {
+ callWithShellPermissionIdentity {
+ roleManager.setBypassingRoleQualification(value)
+ }
+ }
+
+ companion object {
+ private const val ROLE_NAME = RoleManager.ROLE_BROWSER
+ private const val APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk"
+ private const val APP_PACKAGE_NAME = "android.app.role.cts.app"
+ }
+}
diff --git a/tests/cts/role/src/android/app/role/cts/WaitForResultActivity.java b/tests/cts/role/src/android/app/role/cts/WaitForResultActivity.java
new file mode 100644
index 000000000..fb13423d4
--- /dev/null
+++ b/tests/cts/role/src/android/app/role/cts/WaitForResultActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.app.role.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Activity that can start another Activity and wait for its result.
+ */
+public class WaitForResultActivity extends Activity {
+
+ private static final int REQUEST_CODE_WAIT_FOR_RESULT = 1;
+
+ private CountDownLatch mLatch;
+ private int mResultCode;
+ private Intent mData;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ throw new RuntimeException(
+ "Activity was recreated (perhaps due to a configuration change?) "
+ + "and this activity doesn't currently know how to gracefully handle "
+ + "configuration changes.");
+ }
+ }
+
+ public void startActivityToWaitForResult(@NonNull Intent intent) {
+ mLatch = new CountDownLatch(1);
+ startActivityForResult(intent, REQUEST_CODE_WAIT_FOR_RESULT);
+ }
+
+ @NonNull
+ public Pair<Integer, Intent> waitForActivityResult(long timeoutMillis)
+ throws InterruptedException {
+ mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ return new Pair<>(mResultCode, mData);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ if (requestCode == REQUEST_CODE_WAIT_FOR_RESULT) {
+ mResultCode = resultCode;
+ mData = data;
+ mLatch.countDown();
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+}
diff --git a/tests/cts/safetycenter/AndroidTest.xml b/tests/cts/safetycenter/AndroidTest.xml
index 5ec0c380e..6d8c3069c 100644
--- a/tests/cts/safetycenter/AndroidTest.xml
+++ b/tests/cts/safetycenter/AndroidTest.xml
@@ -43,9 +43,12 @@
aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
<option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
diff --git a/tests/cts/safetycenter/TEST_MAPPING b/tests/cts/safetycenter/TEST_MAPPING
index e8c210a5d..b1f60307b 100644
--- a/tests/cts/safetycenter/TEST_MAPPING
+++ b/tests/cts/safetycenter/TEST_MAPPING
@@ -9,7 +9,7 @@
"name": "CtsSafetyCenterTestCases[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
index 33f52b564..c344d7ebd 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterDataTest.kt
@@ -19,7 +19,7 @@ package android.safetycenter.cts
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.Bundle
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntry
@@ -164,7 +164,7 @@ class SafetyCenterDataTest {
SafetyCenterData(status2, listOf(issue2), listOf(entryOrGroup2), listOf(staticEntryGroup2))
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getStatus_withDefaultBuilder_returnsStatus() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -172,7 +172,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getIssues_withDefaultBuilder_returnsEmptyList() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -180,7 +180,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getIssues_whenSetExplicitly_returnsIssues() {
val safetyCenterData =
SafetyCenterData.Builder(status1).addIssue(issue1).addIssue(issue2).build()
@@ -189,7 +189,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getEntriesOrGroups_withDefaultBuilder_returnsEmptyList() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -197,7 +197,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getEntriesOrGroups_whenSetExplicitly_returnsEntriesOrGroups() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -211,7 +211,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getStaticGroups_withDefaultBuilder_returnsEmptyList() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -219,7 +219,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getStaticEntryGroups_whenSetExplicitly_returnsStaticEntryGroups() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -233,7 +233,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDismissedIssues_withDefaultBuilder_returnsEmptyList() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -241,7 +241,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDismissedIssues_whenSetExplicitly_returnsIssues() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -253,7 +253,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_withDefaultBuilder_returnsEmptyBundle() {
val safetyCenterData = SafetyCenterData.Builder(status1).build()
@@ -261,7 +261,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_whenSetExplicitly_returnsExtras() {
val safetyCenterData =
SafetyCenterData.Builder(status1).setExtras(filledExtrasIssuesToGroups1).build()
@@ -275,7 +275,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_whenCleared_returnsEmptyBundle() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -299,7 +299,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDismissedIssues_returnsDismissedIssues() {
val data3 = data1.withDismissedIssuesIfAtLeastU(listOf(issue2))
@@ -308,7 +308,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDismissedIssues_mutationsAreNotAllowed() {
val mutatedDismissedIssues = data1.dismissedIssues
@@ -353,7 +353,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_addIssue_doesNotMutatePreviouslyBuiltInstance() {
val safetyCenterDataBuilder = SafetyCenterData.Builder(status1).addIssue(issue1)
val issues = safetyCenterDataBuilder.build().issues
@@ -364,7 +364,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_clearIssues_removesAllIssues() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -377,7 +377,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_addEntryOrGroup_doesNotMutatePreviouslyBuiltInstance() {
val safetyCenterDataBuilder =
SafetyCenterData.Builder(status1).addEntryOrGroup(entryOrGroup1)
@@ -389,7 +389,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_clearEntriesOrGroups_removesAllEntriesOrGroups() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -402,7 +402,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_addStaticEntryGroup_doesNotMutatePreviouslyBuiltInstance() {
val safetyCenterDataBuilder =
SafetyCenterData.Builder(status1).addStaticEntryGroup(staticEntryGroup1)
@@ -414,7 +414,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_clearStaticEntryGroups_removesAllStaticEntryGroups() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -427,7 +427,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_addDismissedIssue_doesNotMutatePreviouslyBuiltInstance() {
val safetyCenterDataBuilder = SafetyCenterData.Builder(status1).addDismissedIssue(issue1)
val dismissedIssues = safetyCenterDataBuilder.build().dismissedIssues
@@ -438,7 +438,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun builder_clearDismissedIssues_removesAllDismissedIssues() {
val safetyCenterData =
SafetyCenterData.Builder(status1)
@@ -463,7 +463,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_withDismissedIssues_recreatesEqual() {
val data3 = data1.withDismissedIssuesIfAtLeastU(listOf(issue2))
val data4 = data2.withDismissedIssuesIfAtLeastU(listOf(issue1))
@@ -473,7 +473,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_withExtras_recreatesEqual() {
val safetyCenterDataWithExtras = data1.withExtrasIfAtLeastU(filledAllExtras)
val safetyCenterDatafromParcel =
@@ -545,7 +545,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCode_atLeastU_usingEqualsHashCodeToStringTester() {
EqualsHashCodeToStringTester.ofParcelable(
parcelableCreator = SafetyCenterData.CREATOR,
@@ -680,7 +680,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withSingleKnownExtra_containsKnownExtra() {
val safetyCenterDataWithExtras = data1.withExtrasIfAtLeastU(filledExtrasIssuesToGroups1)
@@ -693,7 +693,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withAllKnownExtras_containsKnownExtras() {
val safetyCenterDataWithAllExtras = data1.withExtrasIfAtLeastU(filledAllExtras)
@@ -706,7 +706,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withOneKnowAndOneUnknownExtra_containsKnownAndUnknownExtras() {
val safetyCenterDataWithExtras = data1.withExtrasIfAtLeastU(filledOneKnownOneUnknown)
@@ -719,7 +719,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withSingleUnknownExtra_containsUnknownExtras() {
val safetyCenterDataWithExtras = data1.withExtrasIfAtLeastU(unknownExtras)
@@ -732,7 +732,7 @@ class SafetyCenterDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withoutExtras_containsNoExtras() {
val safetyCenterDataWithoutExtras = data1
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
index 8d44f2736..be7ca343c 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterIssueTest.kt
@@ -19,7 +19,6 @@ package android.safetycenter.cts
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
-import android.os.Build
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetyCenterIssue
@@ -31,8 +30,8 @@ import androidx.test.ext.truth.os.ParcelableSubject.assertThat
import androidx.test.filters.SdkSuppress
import com.android.safetycenter.testing.EqualsHashCodeToStringTester
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFails
import kotlin.test.assertFailsWith
-import org.junit.Assume.assumeFalse
import org.junit.Test
import org.junit.runner.RunWith
@@ -111,7 +110,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getAttributionTitle_returnsAttributionTitle() {
assertThat(
SafetyCenterIssue.Builder(issue1)
@@ -130,7 +129,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getAttributionTitle_withNullAttributionTitle_returnsNull() {
val safetyCenterIssue =
SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
@@ -228,7 +227,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getGroupId_withNonNullValue_returnsGroupId() {
val issue = SafetyCenterIssue.Builder(issue1).setGroupId("group_id").build()
@@ -236,7 +235,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getGroupId_withNullValue_returnsNull() {
val issue =
SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
@@ -247,23 +246,16 @@ class SafetyCenterIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getGroupId_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getGroupId_withVersionLessThanU_throws() {
val issue =
SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
.build()
- val exception = assertFailsWith(UnsupportedOperationException::class) { issue.groupId }
-
- assertThat(exception)
- .hasMessageThat()
- .isEqualTo("Method not supported for versions lower than UPSIDE_DOWN_CAKE")
+ assertFails { issue.groupId }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setGroupId_withNullValue_returnsNull() {
val issue = SafetyCenterIssue.Builder(issue1).setGroupId(null).build()
@@ -272,19 +264,8 @@ class SafetyCenterIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setGroupId_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
-
- val exception =
- assertFailsWith(UnsupportedOperationException::class) {
- SafetyCenterIssue.Builder(issue1).setGroupId("group_id").build()
- }
-
- assertThat(exception)
- .hasMessageThat()
- .isEqualTo("Method not supported for versions lower than UPSIDE_DOWN_CAKE")
+ fun setGroupId_withVersionLessThanU_throws() {
+ assertFails { SafetyCenterIssue.Builder(issue1).setGroupId("group_id").build() }
}
@Test
@@ -300,7 +281,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_recreatesEqual_atLeastAndroidU() {
val safetyCenterIssue =
SafetyCenterIssue.Builder("issue_id", "Everything's good", "Please acknowledge this")
@@ -330,7 +311,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
newUpsideDownCakeEqualsHashCodeToStringTester().test()
}
@@ -373,21 +354,14 @@ class SafetyCenterIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun action_getConfirmationDialogDetails_withVersionLessThanU_throwsUnsupportedOperation() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
-
- assertFailsWith(UnsupportedOperationException::class) { action1.confirmationDialogDetails }
+ fun action_getConfirmationDialogDetails_withVersionLessThanU_throws() {
+ assertFails { action1.confirmationDialogDetails }
}
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun action_setConfirmationDialogDetails_withVersionLessThanU_throwsUnsupportedOperation() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
- assertFailsWith(UnsupportedOperationException::class) {
+ fun action_setConfirmationDialogDetails_withVersionLessThanU_throws() {
+ assertFails {
SafetyCenterIssue.Action.Builder("action_id", "Action label", pendingIntent1)
.setConfirmationDialogDetails(
ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -396,7 +370,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_getConfirmationDialogDetails_withDefaultBuilder_returnsNull() {
val action =
SafetyCenterIssue.Action.Builder("action_id", "Action label", pendingIntent1).build()
@@ -405,7 +379,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_getConfirmationDialogDetails_whenSetExplicitly_returnsConfirmation() {
val action =
SafetyCenterIssue.Action.Builder("action_id", "Action label", pendingIntent1)
@@ -431,7 +405,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_parcelRoundTrip_recreatesEqual_atLeastAndroidU() {
val action =
SafetyCenterIssue.Action.Builder(action1)
@@ -449,7 +423,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
issueActionNewTiramisuEqualsHashCodeToStringTester(
@@ -596,7 +570,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getTitle_returnsTitle() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -604,7 +578,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getText_returnsText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -612,7 +586,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getAcceptButtonText_returnsAcceptButtonText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -620,7 +594,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getDenyButtonText_returnsDenyButtonText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -628,7 +602,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_describeContents_returns0() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -636,7 +610,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_parcelRoundTrip_recreatesEqual() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -644,7 +618,7 @@ class SafetyCenterIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
EqualsHashCodeToStringTester.ofParcelable(
parcelableCreator = ConfirmationDialogDetails.CREATOR
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index b6bb475d8..6193efb71 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -16,8 +16,8 @@
package android.safetycenter.cts
+import android.Manifest.permission.MANAGE_SAFETY_CENTER
import android.content.Context
-import android.os.Build
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.UserHandle.USER_NULL
@@ -40,7 +40,7 @@ import android.safetycenter.cts.testing.FakeExecutor
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.addOnSafetyCenterDataChangedListenerWithPermission
@@ -59,7 +59,6 @@ import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.set
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
import com.android.safetycenter.testing.SafetyCenterEnabledChangedReceiver
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_ALL_OPTIONAL_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_BAREBONE_ID
@@ -77,6 +76,7 @@ import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.STATIC
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestHelper
import com.android.safetycenter.testing.SafetyCenterTestListener
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
@@ -89,15 +89,16 @@ import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_
import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID
import com.android.safetycenter.testing.SafetySourceTestData.Companion.EVENT_SOURCE_STATE_CHANGED
import com.android.safetycenter.testing.SafetySourceTestData.Companion.RECOMMENDATION_ISSUE_ID
+import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.google.common.base.Preconditions.checkState
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
+import kotlin.test.assertFails
import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
-import org.junit.After
-import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
-import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -105,36 +106,14 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterManagerTest {
private val context: Context = getApplicationContext()
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
-
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
@Test
fun isSafetyCenterEnabled_withFlagEnabled_returnsTrue() {
@@ -251,7 +230,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_wronglySignedPackage_throwsIllegalArgumentException() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceWithFakeCert)
@@ -266,7 +245,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_wronglySignedPackageButAllowedByFlag_isAllowed() {
SafetyCenterFlags.allowedAdditionalPackageCerts =
mapOf(context.packageName to setOf(safetyCenterTestConfigs.packageCertHash))
@@ -281,7 +260,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_invalidPackageCertificate_throwsIllegalArgumentException() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceWithInvalidCert)
@@ -309,9 +288,9 @@ class SafetyCenterManagerTest {
assertThat(thrown)
.hasMessageThat()
- .isEqualTo(
- "Safety source: $DYNAMIC_IN_STATELESS_ID is in a stateless group but specified a " +
- "severity level: $SEVERITY_LEVEL_INFORMATION"
+ .matches(
+ "Safety source: $DYNAMIC_IN_STATELESS_ID is in a (stateless|rigid) group but " +
+ "specified a severity level: $SEVERITY_LEVEL_INFORMATION"
)
}
@@ -682,6 +661,18 @@ class SafetyCenterManagerTest {
}
@Test
+ fun getSafetySourceData_differentPackageWithManageSafetyCenterPermission_returnsData() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexConfig)
+
+ val data =
+ callWithShellPermissionIdentity(MANAGE_SAFETY_CENTER) {
+ safetyCenterManager.getSafetySourceData(DYNAMIC_OTHER_PACKAGE_ID)
+ }
+
+ assertThat(data).isNull()
+ }
+
+ @Test
fun getSafetySourceData_differentPackage_throwsIllegalArgumentException() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexConfig)
@@ -834,10 +825,7 @@ class SafetyCenterManagerTest {
val enabledChangedReceiver = SafetyCenterEnabledChangedReceiver(context)
assertFailsWith(TimeoutCancellationException::class) {
- enabledChangedReceiver.setSafetyCenterEnabledWithoutReceiverPermissionAndWait(
- false,
- TIMEOUT_SHORT
- )
+ enabledChangedReceiver.setSafetyCenterEnabledWithoutReceiverPermissionAndWait(false)
}
enabledChangedReceiver.unregister()
}
@@ -874,10 +862,7 @@ class SafetyCenterManagerTest {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
assertFailsWith(TimeoutCancellationException::class) {
- SafetySourceReceiver.setSafetyCenterEnabledWithoutReceiverPermissionAndWait(
- false,
- TIMEOUT_SHORT
- )
+ SafetySourceReceiver.setSafetyCenterEnabledWithoutReceiverPermissionAndWait(false)
}
}
@@ -955,7 +940,7 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT
+ timeout = TIMEOUT_SHORT
)
}
@@ -983,71 +968,6 @@ class SafetyCenterManagerTest {
}
@Test
- fun refreshSafetySources_reasonPageOpen_allowedByFlag_broadcastSent() {
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
- safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
- SafetyCenterFlags.overrideRefreshOnPageOpenSources = setOf(SINGLE_SOURCE_ID)
- SafetySourceReceiver.setResponse(
- Request.Refresh(SINGLE_SOURCE_ID),
- Response.SetData(safetySourceTestData.informationWithIssue)
- )
-
- safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN
- )
-
- val apiSafetySourceData =
- safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
- assertThat(apiSafetySourceData).isEqualTo(safetySourceTestData.informationWithIssue)
- }
-
- @Test
- fun refreshSafetySources_reasonPageOpen_allowedByFlagLater_broadcastSentLater() {
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
- safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
- SafetySourceReceiver.setResponse(
- Request.Refresh(SINGLE_SOURCE_ID),
- Response.SetData(safetySourceTestData.informationWithIssue)
- )
-
- assertFailsWith(TimeoutCancellationException::class) {
- safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT
- )
- }
- val apiSafetySourceDataBeforeSettingFlag =
- safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
- SafetyCenterFlags.overrideRefreshOnPageOpenSources = setOf(SINGLE_SOURCE_ID)
- safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN
- )
- val apiSafetySourceDataAfterSettingFlag =
- safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
-
- assertThat(apiSafetySourceDataBeforeSettingFlag).isEqualTo(safetySourceTestData.information)
- assertThat(apiSafetySourceDataAfterSettingFlag)
- .isEqualTo(safetySourceTestData.informationWithIssue)
- }
-
- @Test
- fun refreshSafetySources_reasonPageOpen_noDataForSource_broadcastSent() {
- safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
- SafetySourceReceiver.setResponse(
- Request.Refresh(SINGLE_SOURCE_ID),
- Response.SetData(safetySourceTestData.information)
- )
-
- safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN
- )
-
- val apiSafetySourceData =
- safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
- assertThat(apiSafetySourceData).isEqualTo(safetySourceTestData.information)
- }
-
- @Test
fun refreshSafetySources_whenSourceClearsData_sourceSendsNullData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
@@ -1135,8 +1055,7 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithoutReceiverPermissionAndWait(
- REFRESH_REASON_RESCAN_BUTTON_CLICK,
- TIMEOUT_SHORT
+ REFRESH_REASON_RESCAN_BUTTON_CLICK
)
}
val apiSafetySourceData =
@@ -1154,7 +1073,7 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT
+ timeout = TIMEOUT_SHORT
)
}
}
@@ -1206,11 +1125,11 @@ class SafetyCenterManagerTest {
)
// Because wrong ID, refresh hasn't finished. Wait for timeout.
- listener.receiveSafetyCenterErrorDetails()
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_LONG)
SafetySourceReceiver.setResponse(
- Request.Rescan(SINGLE_SOURCE_ID),
+ Request.Refresh(SINGLE_SOURCE_ID),
Response.SetData(safetySourceTestData.information)
)
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
@@ -1280,7 +1199,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
assertThat(apiSafetySourceData1).isNull()
// Wait for the ongoing refresh to timeout.
- listener.receiveSafetyCenterErrorDetails()
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_LONG)
SafetySourceReceiver.setResponse(
Request.Refresh(SINGLE_SOURCE_ID),
@@ -1332,18 +1251,11 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- val safetyCenterErrorDetailsFromListener = listener.receiveSafetyCenterErrorDetails()
- assertThat(safetyCenterErrorDetailsFromListener)
- .isEqualTo(
- SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("refresh_timeout")
- )
- )
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
}
@Test
fun refreshSafetySources_withUntrackedSourceThatTimesOut_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
SafetyCenterFlags.untrackedSources = setOf(SOURCE_ID_1)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
// SOURCE_ID_1 will timeout
@@ -1359,14 +1271,11 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
- }
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
}
@Test
fun refreshSafetySources_withMultipleUntrackedSourcesThatTimeOut_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
SafetyCenterFlags.untrackedSources = setOf(SOURCE_ID_1, SOURCE_ID_2)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
// SOURCE_ID_1 and SOURCE_ID_2 will timeout
@@ -1380,9 +1289,7 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
- }
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
}
@Test
@@ -1396,25 +1303,20 @@ class SafetyCenterManagerTest {
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- val safetyCenterErrorDetailsFromListener = listener.receiveSafetyCenterErrorDetails()
- assertThat(safetyCenterErrorDetailsFromListener)
- .isEqualTo(
- SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("refresh_timeout")
- )
- )
+ listener.waitForSafetyCenterRefresh(withErrorEntry = true)
}
@Test
fun refreshSafetySources_withTrackedSourceThatHasNoReceiver_doesNotTimeOut() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceOtherPackageConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithPermission(REFRESH_REASON_RESCAN_BUTTON_CLICK)
assertFailsWith(TimeoutCancellationException::class) {
- listener.receiveSafetyCenterErrorDetails(TIMEOUT_SHORT)
+ // In this case a refresh isn't even started because there is only a single source
+ // without a receiver.
+ listener.receiveSafetyCenterData(TIMEOUT_SHORT)
}
}
@@ -1426,7 +1328,7 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT
+ timeout = TIMEOUT_SHORT
)
}
}
@@ -1510,7 +1412,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun refreshSafetySources_withRefreshReasonPeriodic_noBackgroundRefreshSourceDoesNotSendData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
SafetySourceReceiver.setResponse(
@@ -1522,7 +1424,7 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PERIODIC,
- TIMEOUT_SHORT
+ timeout = TIMEOUT_SHORT
)
}
@@ -1532,7 +1434,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun refreshSafetySources_withRefreshReasonPeriodic_backgroundRefreshSourceSendsData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
SafetySourceReceiver.setResponse(
@@ -1549,7 +1451,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun refreshSafetySources_withSafetySourceIds_onlySpecifiedSourcesSendData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
SafetySourceReceiver.apply {
@@ -1584,7 +1486,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun refreshSafetySources_withEmptySafetySourceIds_noSourcesSendData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
SafetySourceReceiver.setResponse(
@@ -1595,8 +1497,8 @@ class SafetyCenterManagerTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT,
- emptyList()
+ safetySourceIds = emptyList(),
+ timeout = TIMEOUT_SHORT,
)
}
@@ -1606,27 +1508,19 @@ class SafetyCenterManagerTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun refreshSafetySources_versionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun refreshSafetySources_versionLessThanU_throws() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
- val exception =
- assertFailsWith(UnsupportedOperationException::class) {
- safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
- REFRESH_REASON_PAGE_OPEN,
- safetySourceIds = listOf(SOURCE_ID_1, SOURCE_ID_3)
- )
- }
-
- assertThat(exception)
- .hasMessageThat()
- .isEqualTo("Method not supported for versions lower than UPSIDE_DOWN_CAKE")
+ assertFails {
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN,
+ safetySourceIds = listOf(SOURCE_ID_1, SOURCE_ID_3)
+ )
+ }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun refreshSafetySources_withSafetySourceIds_withoutPermission_throwsSecurityException() {
assertFailsWith(SecurityException::class) {
safetyCenterManager.refreshSafetySources(REFRESH_REASON_PAGE_OPEN, listOf())
@@ -2076,7 +1970,7 @@ class SafetyCenterManagerTest {
assertThat(error)
.isEqualTo(
SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("redirecting_error")
+ safetyCenterResourcesApk.getStringByName("redirecting_error")
)
)
}
@@ -2102,7 +1996,7 @@ class SafetyCenterManagerTest {
assertThat(error)
.isEqualTo(
SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("resolving_action_error")
+ safetyCenterResourcesApk.getStringByName("resolving_action_error")
)
)
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
index 695265059..d882fc3cb 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterUnsupportedTest.kt
@@ -42,12 +42,12 @@ import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.rep
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.setSafetyCenterConfigForTestsWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
import com.android.safetycenter.testing.SafetyCenterEnabledChangedReceiver
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestHelper
import com.android.safetycenter.testing.SafetyCenterTestListener
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceReceiver
import com.android.safetycenter.testing.SafetySourceReceiver.Companion.executeSafetyCenterIssueActionWithPermissionAndWait
import com.android.safetycenter.testing.SafetySourceReceiver.Companion.refreshSafetySourcesWithReceiverPermissionAndWait
@@ -56,14 +56,13 @@ import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_
import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID
import com.android.safetycenter.testing.SafetySourceTestData.Companion.EVENT_SOURCE_STATE_CHANGED
import com.android.safetycenter.testing.SettingsPackage.getSettingsPackageName
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
-import org.junit.After
import org.junit.Assume.assumeTrue
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -72,39 +71,17 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterUnsupportedTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = getApplicationContext()
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = !context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceDoesntSupportSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
+ @get:Rule(order = 1)
+ val supportsSafetyCenterRule = SupportsSafetyCenterRule(context, requireSupportIs = false)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Test
fun launchActivity_opensSettings() {
@@ -238,7 +215,7 @@ class SafetyCenterUnsupportedTest {
assertFailsWith(TimeoutCancellationException::class) {
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN,
- TIMEOUT_SHORT
+ timeout = TIMEOUT_SHORT
)
}
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
index 3dec4f509..4d1cb6a8b 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
@@ -16,7 +16,7 @@
package android.safetycenter.cts
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED
import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
@@ -190,7 +190,7 @@ class SafetyEventTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
newTiramisuEqualsHashCodeToStringTester(
createCopyFromBuilder = { SafetyEvent.Builder(it).build() }
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
index d7208c098..ba2ab3d76 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
@@ -20,7 +20,7 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.Bundle
import android.safetycenter.SafetySourceData
import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
@@ -96,7 +96,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_withDefaultBuilder_returnsEmptyBundle() {
val safetySourceData =
SafetySourceData.Builder().setStatus(createStatus(SEVERITY_LEVEL_INFORMATION)).build()
@@ -105,7 +105,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_whenSetExplicitly_returnsExtras() {
val safetySourceData =
SafetySourceData.Builder()
@@ -118,7 +118,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getExtras_whenCleared_returnsEmptyBundle() {
val safetySourceData =
SafetySourceData.Builder()
@@ -325,7 +325,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_withExtras_recreatesEqual() {
val safetySourceData =
SafetySourceData.Builder()
@@ -384,7 +384,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCode_atLeastU_usingEqualsHashCodeToStringTester() {
val firstStatus = createStatus(SEVERITY_LEVEL_INFORMATION, 1)
val secondStatus = createStatus(SEVERITY_LEVEL_INFORMATION, 2)
@@ -454,7 +454,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withExtras_containsHasExtras() {
val safetySourceDataWithExtras =
SafetySourceData.Builder()
@@ -468,7 +468,7 @@ class SafetySourceDataTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun toString_withoutExtras_doesNotContainHasExtras() {
val safetySourceDataWithoutExtras =
SafetySourceData.Builder().setStatus(createStatus(SEVERITY_LEVEL_INFORMATION)).build()
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
index 4749c3616..2d19a3175 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceIssueTest.kt
@@ -20,7 +20,6 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
-import android.os.Build
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
@@ -42,8 +41,8 @@ import androidx.test.filters.SdkSuppress
import com.android.modules.utils.build.SdkLevel
import com.android.safetycenter.testing.EqualsHashCodeToStringTester
import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFails
import kotlin.test.assertFailsWith
-import org.junit.Assume.assumeFalse
import org.junit.Test
import org.junit.runner.RunWith
@@ -119,22 +118,16 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun action_getConfirmationDialogDetails_withVersionLessThanU_throwsUnsupportedOperation() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun action_getConfirmationDialogDetails_withVersionLessThanU_throws() {
val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
- assertFailsWith(UnsupportedOperationException::class) { action.confirmationDialogDetails }
+ assertFails { action.confirmationDialogDetails }
}
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun action_setConfirmationDialogDetails_withVersionLessThanU_throwsUnsupportedOperation() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
- assertFailsWith(UnsupportedOperationException::class) {
+ fun action_setConfirmationDialogDetails_withVersionLessThanU_throws() {
+ assertFails {
Action.Builder("action_id", "Action label", pendingIntent1)
.setConfirmationDialogDetails(
ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -143,7 +136,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_getConfirmationDialogDetails_withDefaultBuilder_returnsNull() {
val action = Action.Builder("action_id", "Action label", pendingIntent1).build()
@@ -151,7 +144,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_getConfirmationDialogDetails_whenSetExplicitly_returnsConfirmation() {
val action =
Action.Builder("action_id", "Action label", pendingIntent1)
@@ -186,7 +179,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_build_withActivityPendingIntentAndWillResolve_throwsIllegalArgumentException() {
assertFailsWith(IllegalArgumentException::class) {
Action.Builder("action_id", "Action label", pendingIntent1).setWillResolve(true).build()
@@ -211,7 +204,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_parcelRoundTrip_recreatesEqual_atLeastAndroidU() {
val action =
Action.Builder("action_id", "Action label", pendingIntent1)
@@ -229,7 +222,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun action_equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
actionNewTiramisuEqualsHashCodeToStringTester(
@@ -293,7 +286,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_getTitle_returnsTitle() {
val notification = Notification.Builder("Notification title", "Notification text").build()
@@ -301,7 +294,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_getText_returnsText() {
val notification = Notification.Builder("Notification title", "Notification text").build()
@@ -309,7 +302,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_getActions_withDefaultBuilder_returnsEmptyList() {
val notification = Notification.Builder("", "").build()
@@ -317,7 +310,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_getActions_returnsActions() {
val notification =
Notification.Builder("", "").addAction(action1).addAction(action2).build()
@@ -326,7 +319,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_getActions_mutationsAreNotAllowed() {
val notification =
Notification.Builder("", "").addAction(action1).addAction(action2).build()
@@ -335,7 +328,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_describeContents_returns0() {
val notification =
Notification.Builder("Notification title", "Notification text")
@@ -347,7 +340,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_parcelRoundTrip_recreatesEqual() {
val notification =
Notification.Builder("Notification title", "Notification text")
@@ -359,7 +352,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_withNullTitle_throwsNullPointerException() {
assertFailsWith(NullPointerException::class) {
Notification.Builder(Generic.asNull(), "Notification text")
@@ -367,7 +360,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_withNullText_throwsNullPointerException() {
assertFailsWith(NullPointerException::class) {
Notification.Builder("Notification title", Generic.asNull())
@@ -375,7 +368,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_addAction_doesNotMutatePreviouslyBuiltInstance() {
val notificationBuilder = Notification.Builder("", "").addAction(action1)
val actions = notificationBuilder.build().actions
@@ -386,7 +379,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_addAction_withNull_throwsIllegalArgumentException() {
assertFailsWith(NullPointerException::class) {
Notification.Builder("", "").addAction(Generic.asNull())
@@ -394,7 +387,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_addActions_keepsPreviouslyAddedActions() {
val notificationBuilder = Notification.Builder("", "").addAction(action1)
@@ -404,7 +397,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_addActions_doesNotMutatePreviouslyBuiltInstance() {
val notificationBuilder = Notification.Builder("", "").addActions(listOf(action1))
val actions = notificationBuilder.build().actions
@@ -415,7 +408,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_addActions_withNull_throwsIllegalArgumentException() {
assertFailsWith(NullPointerException::class) {
Notification.Builder("", "").addActions(Generic.asNull())
@@ -423,7 +416,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_builder_clearActions_removesAllActions() {
val notification =
Notification.Builder("", "")
@@ -437,7 +430,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_build_withDuplicateActionIds_throwsIllegalArgumentException() {
val notificationBuilder =
Notification.Builder("Notification title", "Notification text")
@@ -452,7 +445,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_build_withMoreThanTwoActions_throwsIllegalArgumentException() {
val notificationBuilder =
Notification.Builder("Notification title", "Notification text")
@@ -468,7 +461,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun notification_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
EqualsHashCodeToStringTester.ofParcelable(
parcelableCreator = Notification.CREATOR,
@@ -490,7 +483,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getTitle_returnsTitle() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -498,7 +491,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getText_returnsText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -506,7 +499,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getAcceptButtonText_returnsAcceptButtonText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -514,7 +507,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_getDenyButtonText_returnsDenyButtonText() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -522,7 +515,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_describeContents_returns0() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -530,7 +523,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_parcelRoundTrip_recreatesEqual() {
val confirmationDialogDetails = ConfirmationDialogDetails("Title", "Text", "Accept", "Deny")
@@ -538,7 +531,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun actionConfirmation_equalsHashCodeToString_usingEqualsHashCodeToStringTester() {
EqualsHashCodeToStringTester.ofParcelable(
parcelableCreator = ConfirmationDialogDetails.CREATOR
@@ -636,7 +629,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getAttributionTitle_withNullAttributionTitle_returnsNull() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -653,7 +646,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getAttributionTitle_returnsAttributionTitle() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -672,10 +665,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getAttributionTitle_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getAttributionTitle_withVersionLessThanU_throws() {
val safetySourceIssue =
SafetySourceIssue.Builder(
"Issue id",
@@ -687,15 +677,12 @@ class SafetySourceIssueTest {
.addAction(action1)
.build()
- assertFailsWith(UnsupportedOperationException::class) { safetySourceIssue.attributionTitle }
+ assertFails { safetySourceIssue.attributionTitle }
}
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setAttributionTitle_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun setAttributionTitle_withVersionLessThanU_throws() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
"Issue id",
@@ -705,9 +692,7 @@ class SafetySourceIssueTest {
"issue_type_id"
)
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssueBuilder.setAttributionTitle("title")
- }
+ assertFails { safetySourceIssueBuilder.setAttributionTitle("title") }
}
@Test
@@ -760,7 +745,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getIssueCategory_whenSetExplicitlyWithUValueOnU_returnsIssueCategory() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -884,7 +869,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDeduplicationId_withDefaultBuilder_returnsNull() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -901,7 +886,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getDeduplicationId_whenSetExplicitly_returnsDeduplicationId() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -920,10 +905,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getDeduplicationId_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getDeduplicationId_withVersionLessThanU_throws() {
val safetySourceIssue =
SafetySourceIssue.Builder(
"Issue id",
@@ -935,15 +917,12 @@ class SafetySourceIssueTest {
.addAction(action1)
.build()
- assertFailsWith(UnsupportedOperationException::class) { safetySourceIssue.deduplicationId }
+ assertFails { safetySourceIssue.deduplicationId }
}
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setDeduplicationId_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun setDeduplicationId_withVersionLessThanU_throws() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
"Issue id",
@@ -953,9 +932,7 @@ class SafetySourceIssueTest {
"issue_type_id"
)
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssueBuilder.setDeduplicationId("id")
- }
+ assertFails { safetySourceIssueBuilder.setDeduplicationId("id") }
}
@Test
@@ -975,7 +952,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getCustomNotification_withDefaultBuilder_returnsNull() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -992,7 +969,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getCustomNotification_whenSetExplicitly_returnsCustomNotification() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1020,10 +997,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getCustomNotification_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getCustomNotification_withVersionLessThanU_throws() {
val safetySourceIssue =
SafetySourceIssue.Builder(
"Issue id",
@@ -1035,17 +1009,12 @@ class SafetySourceIssueTest {
.addAction(action1)
.build()
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssue.customNotification
- }
+ assertFails { safetySourceIssue.customNotification }
}
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setCustomNotification_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun setCustomNotification_withVersionLessThanU_throws() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
"Issue id",
@@ -1055,13 +1024,11 @@ class SafetySourceIssueTest {
"issue_type_id"
)
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssueBuilder.setCustomNotification(null)
- }
+ assertFails { safetySourceIssueBuilder.setCustomNotification(null) }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getNotificationBehavior_withDefaultBuilder_returnsUnspecified() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1079,7 +1046,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getNotificationBehavior_whenSetExplicitly_returnsSpecifiedBehavior() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1099,10 +1066,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getNotificationBehavior_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getNotificationBehavior_withVersionLessThanU_throws() {
val safetySourceIssue =
SafetySourceIssue.Builder(
"Issue id",
@@ -1114,13 +1078,11 @@ class SafetySourceIssueTest {
.addAction(action1)
.build()
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssue.notificationBehavior
- }
+ assertFails { safetySourceIssue.notificationBehavior }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setNotificationBehavior_withInvalidNotificationBehavior_throwsIllegalArgumentException() {
val builder =
SafetySourceIssue.Builder(
@@ -1141,10 +1103,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setNotificationBehavior_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun setNotificationBehavior_withVersionLessThanU_throws() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
"Issue id",
@@ -1154,13 +1113,11 @@ class SafetySourceIssueTest {
"issue_type_id"
)
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssueBuilder.setNotificationBehavior(0)
- }
+ assertFails { safetySourceIssueBuilder.setNotificationBehavior(0) }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getIssueActionability_withDefaultBuilder_returnsManual() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1178,7 +1135,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getIssueActionability_whenSetExplicitly_returnsValueSet() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1198,10 +1155,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun getIssueActionability_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun getIssueActionability_withVersionLessThanU_throws() {
val safetySourceIssue =
SafetySourceIssue.Builder(
"Issue id",
@@ -1213,13 +1167,11 @@ class SafetySourceIssueTest {
.addAction(action1)
.build()
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssue.issueActionability
- }
+ assertFails { safetySourceIssue.issueActionability }
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setIssueActionability_withInvalidIssueActionability_throwsIllegalArgumentException() {
val builder =
SafetySourceIssue.Builder(
@@ -1240,10 +1192,7 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
- fun setIssueActionability_withVersionLessThanU_throwsUnsupportedOperationException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
+ fun setIssueActionability_withVersionLessThanU_throws() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
"Issue id",
@@ -1253,9 +1202,7 @@ class SafetySourceIssueTest {
"issue_type_id"
)
- assertFailsWith(UnsupportedOperationException::class) {
- safetySourceIssueBuilder.setIssueActionability(0)
- }
+ assertFails { safetySourceIssueBuilder.setIssueActionability(0) }
}
@Test
@@ -1366,9 +1313,6 @@ class SafetySourceIssueTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
fun build_withUIssueCategoryValueOnT_throwsIllegalArgumentException() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
val builder =
SafetySourceIssue.Builder(
"Issue id",
@@ -1480,7 +1424,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_withNoActionsAndManualActionabilityOnU_throwsIllegalArgumentException() {
val safetySourceIssueBuilder =
SafetySourceIssue.Builder(
@@ -1500,7 +1444,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_withNoActionsAndTipActionabilityOnU_success() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1517,7 +1461,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_withNoActionsAndAutomaticActionabilityOnU_success() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1574,7 +1518,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_recreatesEqual_atLeastAndroidU() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1601,7 +1545,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun parcelRoundTrip_recreatesEqual_atLeastUpsideDownCake() {
val safetySourceIssue =
SafetySourceIssue.Builder(
@@ -1636,7 +1580,7 @@ class SafetySourceIssueTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastUpsideDownCake() {
newUpsideDownCakeEqualsHashCodeToStringTester().test()
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
index 5aeea21f1..2a20cd45d 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/SafetySourceStatusTest.kt
@@ -20,7 +20,7 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
import android.content.Intent
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING
import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_INFORMATION
import android.safetycenter.SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED
@@ -285,7 +285,7 @@ class SafetySourceStatusTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
newTiramisuEqualsHashCodeToStringTester(
createCopyFromBuilder = { SafetySourceStatus.Builder(it).build() }
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt
index 7dff9dd54..68dcd4a11 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetyCenterConfigTest.kt
@@ -16,7 +16,7 @@
package android.safetycenter.cts.config
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.config.SafetyCenterConfig
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.truth.os.ParcelableSubject.assertThat
@@ -86,7 +86,7 @@ class SafetyCenterConfigTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun equalsHashCodeToString_usingEqualsHashCodeToStringTester_atLeastAndroidU() {
newTiramisuEqualsHashCodeToStringTester(
createCopyFromBuilder = { SafetyCenterConfig.Builder(it).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
index 055e82ad3..59cc6547a 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourceTest.kt
@@ -17,7 +17,7 @@
package android.safetycenter.cts.config
import android.content.res.Resources
-import android.os.Build
+import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.safetycenter.config.SafetySource
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.truth.os.ParcelableSubject.assertThat
@@ -75,7 +75,7 @@ class SafetySourceTest {
}
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getOptionalPackageName_returnsPackageNameOrNull() {
assertThat(DYNAMIC_BAREBONE.optionalPackageName).isEqualTo(PACKAGE_NAME)
assertThat(dynamicAllOptional().optionalPackageName).isEqualTo(PACKAGE_NAME)
@@ -259,7 +259,7 @@ class SafetySourceTest {
assertThat(issueOnlyAllOptional().isRefreshOnPageOpenAllowed).isEqualTo(true)
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
@Test
fun areNotificationsAllowed_returnsNotificationsAllowed() {
assertThat(DYNAMIC_BAREBONE.areNotificationsAllowed()).isFalse()
@@ -273,7 +273,7 @@ class SafetySourceTest {
assertThat(issueOnlyAllOptional().areNotificationsAllowed()).isTrue()
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
@Test
fun getDeduplicationGroupsList_returnsDeduplicationGroups() {
assertThat(DYNAMIC_BAREBONE.deduplicationGroup).isNull()
@@ -287,7 +287,7 @@ class SafetySourceTest {
assertThat(issueOnlyAllOptional().deduplicationGroup).isEqualTo(DEDUPLICATION_GROUP)
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
@Test
fun getPackageCertificateHashes_returnsPackageCerts() {
assertThat(DYNAMIC_BAREBONE.packageCertificateHashes).isEmpty()
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt
index 015d18842..f741369eb 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/SafetySourcesGroupTest.kt
@@ -211,7 +211,7 @@ class SafetySourcesGroupTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_hiddenGroupWithDynamicSource_throwsIllegalStateException() {
val builder =
SafetySourcesGroup.Builder()
@@ -228,7 +228,7 @@ class SafetySourcesGroupTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_hiddenGroupWithStaticSource_throwsIllegalStateException() {
val builder =
SafetySourcesGroup.Builder()
@@ -245,7 +245,7 @@ class SafetySourcesGroupTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_statefulGroupWithIssueOnlySource_throwsIllegalStateException() {
val builder =
SafetySourcesGroup.Builder()
@@ -264,7 +264,7 @@ class SafetySourcesGroupTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun build_statelessGroupWithIssueOnlySource_throwsIllegalStateException() {
val builder =
SafetySourcesGroup.Builder()
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt
index 32959629c..7c9e2cffc 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/config/XmlConfigTest.kt
@@ -24,15 +24,14 @@ import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_ISSUE_ONLY
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.safetycenter.config.SafetyCenterConfigParser
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterConfigWithPermission
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
-import org.junit.After
-import org.junit.Assume.assumeTrue
-import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -40,33 +39,12 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class XmlConfigTest {
private val context: Context = getApplicationContext()
- private val safetyCenterContext = SafetyCenterResourcesContext.forTests(context)
- private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
-
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2)
+ val safetyCenterTestRule = SafetyCenterTestRule(SafetyCenterTestHelper(context))
@Test
fun safetyCenterConfigResource_validConfig() {
@@ -93,7 +71,7 @@ class XmlConfigTest {
}
private fun assertThatIntentResolves(intentAction: String) {
- val pm = safetyCenterContext.packageManager
+ val pm = context.packageManager
assertWithMessage("Intent '%s' cannot be resolved.", intentAction)
.that(pm.queryIntentActivities(Intent(intentAction), ResolveInfoFlags.of(0)))
.isNotEmpty()
@@ -109,8 +87,8 @@ class XmlConfigTest {
private fun parseXmlConfig() =
SafetyCenterConfigParser.parseXmlResource(
- safetyCenterContext.safetyCenterConfig!!,
- safetyCenterContext.resources!!
+ safetyCenterResourcesApk.safetyCenterConfig!!,
+ safetyCenterResourcesApk.resources
)
companion object {
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/ui/SafetyCenterActivityTest.kt b/tests/cts/safetycenter/src/android/safetycenter/cts/ui/SafetyCenterActivityTest.kt
index 8fb56b09e..111f01243 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/ui/SafetyCenterActivityTest.kt
+++ b/tests/cts/safetycenter/src/android/safetycenter/cts/ui/SafetyCenterActivityTest.kt
@@ -24,15 +24,14 @@ import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
import com.android.compatibility.common.util.UiAutomatorUtils2.getUiDevice
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SettingsPackage.getSettingsPackageName
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.resetRotation
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
import org.junit.After
-import org.junit.Assume.assumeTrue
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,36 +40,16 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterActivityTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = getApplicationContext()
-
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@After
fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
getUiDevice().resetRotation()
}
diff --git a/tests/functional/safetycenter/multiusers/AndroidTest.xml b/tests/functional/safetycenter/multiusers/AndroidTest.xml
index c1e19d2e4..20032357a 100644
--- a/tests/functional/safetycenter/multiusers/AndroidTest.xml
+++ b/tests/functional/safetycenter/multiusers/AndroidTest.xml
@@ -43,9 +43,12 @@
aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
<option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
diff --git a/tests/functional/safetycenter/multiusers/TEST_MAPPING b/tests/functional/safetycenter/multiusers/TEST_MAPPING
index aedf92b86..65f53b453 100644
--- a/tests/functional/safetycenter/multiusers/TEST_MAPPING
+++ b/tests/functional/safetycenter/multiusers/TEST_MAPPING
@@ -1,30 +1,11 @@
{
- "presubmit": [
- {
- "name": "SafetyCenterFunctionalMultiUsersTestCases",
- "options": [
- {
- "exclude-annotation": "com.android.bedstead.harrier.annotations.Postsubmit"
- }
- ]
- }
- ],
"postsubmit": [
+ // Note that these test cases are running in postsubmit only. Bedstead tests can be pretty slow
+ // (due to adding/removing users, which makes the device somewhat unresponsive). This can also
+ // cause flakyness due to timeouts. In postsubmit, these tests have more time to run which makes
+ // them less flaky (and this flakyness is arguably less of an issue in this case).
{
"name": "SafetyCenterFunctionalMultiUsersTestCases"
}
- ],
- "mainline-presubmit": [
- {
- "name": "SafetyCenterFunctionalMultiUsersTestCases[com.google.android.permission.apex]",
- "options": [
- {
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
- },
- {
- "exclude-annotation": "com.android.bedstead.harrier.annotations.Postsubmit"
- }
- ]
- }
]
}
diff --git a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
index 07ae129ec..9534b597a 100644
--- a/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
+++ b/tests/functional/safetycenter/multiusers/src/android/safetycenter/functional/multiusers/SafetyCenterMultiUsersTest.kt
@@ -23,6 +23,7 @@ import android.content.Context
import android.content.Intent
import android.os.UserHandle
import android.safetycenter.SafetyCenterData
+import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING
import android.safetycenter.SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN
import android.safetycenter.SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED
@@ -30,30 +31,34 @@ import android.safetycenter.SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_
import android.safetycenter.SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY
import android.safetycenter.SafetyCenterEntryGroup
import android.safetycenter.SafetyCenterEntryOrGroup
+import android.safetycenter.SafetyCenterIssue
import android.safetycenter.SafetyCenterManager
import android.safetycenter.SafetyCenterStaticEntry
import android.safetycenter.SafetyCenterStaticEntryGroup
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceData
import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.LargeTest
import com.android.bedstead.harrier.BedsteadJUnit4
import com.android.bedstead.harrier.DeviceState
import com.android.bedstead.harrier.annotations.EnsureHasAdditionalUser
import com.android.bedstead.harrier.annotations.EnsureHasCloneProfile
import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile
-import com.android.bedstead.harrier.annotations.Postsubmit
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner
+import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner
import com.android.bedstead.nene.TestApis
import com.android.bedstead.nene.types.OptionalBoolean.TRUE
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
+import com.android.safetycenter.testing.NotificationCharacteristics
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterDataWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetySourceDataWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.setSafetySourceDataWithPermission
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
+import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.DYNAMIC_BAREBONE_ID
@@ -76,27 +81,30 @@ import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.STATIC
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestData.Companion.withoutExtras
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceTestData
import com.android.safetycenter.testing.SafetySourceTestData.Companion.EVENT_SOURCE_STATE_CHANGED
+import com.android.safetycenter.testing.SafetySourceTestData.Companion.ISSUE_TYPE_ID
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
+import com.android.safetycenter.testing.TestNotificationListener
import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitAllTextNotDisplayed
import com.google.common.base.Preconditions.checkState
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertFailsWith
import org.junit.After
-import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.ClassRule
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
/**
* Functional tests for our APIs and UI on a device with multiple users. e.g. with a managed or
- * secondary user(s).
+ * additional user(s).
*/
+@LargeTest
@RunWith(BedsteadJUnit4::class)
class SafetyCenterMultiUsersTest {
@@ -104,70 +112,65 @@ class SafetyCenterMultiUsersTest {
@JvmField @ClassRule @Rule val deviceState: DeviceState = DeviceState()
}
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = ApplicationProvider.getApplicationContext()
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestData = SafetyCenterTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
private var inQuietMode = false
- private val primaryProfileOnlyIssues =
- listOf(
- safetyCenterTestData.safetyCenterIssueCritical(
- DYNAMIC_BAREBONE_ID,
- groupId = DYNAMIC_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueCritical(
- ISSUE_ONLY_BAREBONE_ID,
- attributionTitle = null,
- groupId = ISSUE_ONLY_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueRecommendation(
- DYNAMIC_DISABLED_ID,
- groupId = DYNAMIC_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueRecommendation(
- ISSUE_ONLY_ALL_OPTIONAL_ID,
- attributionTitle = null,
- groupId = ISSUE_ONLY_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueInformation(
- DYNAMIC_IN_STATELESS_ID,
- groupId = MIXED_STATELESS_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueInformation(
- ISSUE_ONLY_IN_STATELESS_ID,
- groupId = MIXED_STATELESS_GROUP_ID
+ private val primaryProfileOnlyIssues: List<SafetyCenterIssue>
+ get() =
+ listOf(
+ safetyCenterTestData.safetyCenterIssueCritical(
+ DYNAMIC_BAREBONE_ID,
+ groupId = DYNAMIC_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueCritical(
+ ISSUE_ONLY_BAREBONE_ID,
+ attributionTitle = null,
+ groupId = ISSUE_ONLY_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueRecommendation(
+ DYNAMIC_DISABLED_ID,
+ groupId = DYNAMIC_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueRecommendation(
+ ISSUE_ONLY_ALL_OPTIONAL_ID,
+ attributionTitle = null,
+ groupId = ISSUE_ONLY_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueInformation(
+ DYNAMIC_IN_STATELESS_ID,
+ groupId = MIXED_STATELESS_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueInformation(
+ ISSUE_ONLY_IN_STATELESS_ID,
+ groupId = MIXED_STATELESS_GROUP_ID
+ )
)
- )
- private val dynamicBareboneDefault =
- safetyCenterTestData.safetyCenterEntryDefault(DYNAMIC_BAREBONE_ID)
+ private val dynamicBareboneDefault: SafetyCenterEntry
+ get() = safetyCenterTestData.safetyCenterEntryDefault(DYNAMIC_BAREBONE_ID)
- private val dynamicBareboneUpdated =
- safetyCenterTestData.safetyCenterEntryCritical(DYNAMIC_BAREBONE_ID)
+ private val dynamicBareboneUpdated: SafetyCenterEntry
+ get() = safetyCenterTestData.safetyCenterEntryCritical(DYNAMIC_BAREBONE_ID)
- private val dynamicDisabledDefault =
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_DISABLED_ID)
- .setPendingIntent(null)
- .setEnabled(false)
- .build()
+ private val dynamicDisabledDefault: SafetyCenterEntry
+ get() =
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_DISABLED_ID)
+ .setPendingIntent(null)
+ .setEnabled(false)
+ .build()
- private val dynamicDisabledUpdated =
- safetyCenterTestData.safetyCenterEntryRecommendation(DYNAMIC_DISABLED_ID)
+ private val dynamicDisabledUpdated: SafetyCenterEntry
+ get() = safetyCenterTestData.safetyCenterEntryRecommendation(DYNAMIC_DISABLED_ID)
- private val dynamicDisabledForWorkDefaultBuilder
+ private val dynamicDisabledForWorkDefaultBuilder: SafetyCenterEntry.Builder
get() =
safetyCenterTestData
.safetyCenterEntryDefaultBuilder(
@@ -178,26 +181,54 @@ class SafetyCenterMultiUsersTest {
.setPendingIntent(null)
.setEnabled(false)
- private val dynamicDisabledForWorkDefault
+ private val dynamicDisabledForWorkDefault: SafetyCenterEntry
get() = dynamicDisabledForWorkDefaultBuilder.build()
- private val dynamicDisabledForWorkPaused
+ private val dynamicDisabledForWorkPausedUpdated: SafetyCenterEntry
get() =
- dynamicDisabledForWorkDefaultBuilder
- // TODO(b/233188021): This needs to use the Enterprise API to override the "work"
- // keyword.
- .setSummary(safetyCenterResourcesContext.getStringByName("work_profile_paused"))
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(
+ DYNAMIC_DISABLED_ID,
+ deviceState.workProfile().id(),
+ title = "Ok title for Work",
+ pendingIntent = null
+ )
+ .setSummary(
+ safetyCenterResourcesApk.getStringByName("work_profile_paused"),
+ )
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
+ .setEnabled(false)
.build()
- private val dynamicDisabledForWorkUpdated
+ private val dynamicDisabledForWorkUpdated: SafetyCenterEntry
get() = safetyCenterEntryOkForWork(DYNAMIC_DISABLED_ID, deviceState.workProfile().id())
- private val dynamicHiddenUpdated =
- safetyCenterTestData.safetyCenterEntryUnspecified(DYNAMIC_HIDDEN_ID, pendingIntent = null)
+ private val dynamicHiddenUpdated: SafetyCenterEntry
+ get() =
+ safetyCenterTestData.safetyCenterEntryUnspecified(
+ DYNAMIC_HIDDEN_ID,
+ pendingIntent = null
+ )
- private val dynamicHiddenForWorkUpdated
+ private val dynamicHiddenForWorkUpdated: SafetyCenterEntry
get() = safetyCenterEntryOkForWork(DYNAMIC_HIDDEN_ID, deviceState.workProfile().id())
+ private val dynamicHiddenForWorkPausedUpdated
+ get() =
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(
+ DYNAMIC_HIDDEN_ID,
+ deviceState.workProfile().id(),
+ title = "Ok title for Work",
+ pendingIntent = null
+ )
+ .setSummary(
+ safetyCenterResourcesApk.getStringByName("work_profile_paused"),
+ )
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
+ .setEnabled(false)
+ .build()
+
private val staticGroupBuilder =
SafetyCenterEntryGroup.Builder(STATIC_GROUP_ID, "OK")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
@@ -213,70 +244,78 @@ class SafetyCenterMultiUsersTest {
private val staticAllOptional =
safetyCenterTestData.safetyCenterEntryDefaultStaticBuilder(STATIC_ALL_OPTIONAL_ID).build()
- private val staticAllOptionalForWorkBuilder
- get() =
- safetyCenterTestData
- .safetyCenterEntryDefaultStaticBuilder(
- STATIC_ALL_OPTIONAL_ID,
- userId = deviceState.workProfile().id(),
- title = "Paste"
- )
- .setPendingIntent(
- createTestActivityRedirectPendingIntentForUser(
- deviceState.workProfile().userHandle()
- )
+ private fun staticAllOptionalForWorkBuilder(inQuietMode: Boolean = false) =
+ safetyCenterTestData
+ .safetyCenterEntryDefaultStaticBuilder(
+ STATIC_ALL_OPTIONAL_ID,
+ userId = deviceState.workProfile().id(),
+ title = "Paste"
+ )
+ .setPendingIntent(
+ createTestActivityRedirectPendingIntentForUser(
+ deviceState.workProfile().userHandle(),
+ inQuietMode
)
+ )
private val staticAllOptionalForWork
- get() = staticAllOptionalForWorkBuilder.build()
+ get() = staticAllOptionalForWorkBuilder().build()
private val staticAllOptionalForWorkPaused
get() =
- staticAllOptionalForWorkBuilder
- // TODO(b/233188021): This needs to use the Enterprise API to override the "work"
- // keyword.
- .setSummary(safetyCenterResourcesContext.getStringByName("work_profile_paused"))
+ staticAllOptionalForWorkBuilder(inQuietMode = true)
+ .setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
.setEnabled(false)
.build()
- private val staticEntry =
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
-
- private val staticEntryUpdated =
- SafetyCenterStaticEntry.Builder("Unspecified title")
- .setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
-
- private val staticEntryForWorkBuilder
+ private val staticEntry: SafetyCenterStaticEntry
get() =
- SafetyCenterStaticEntry.Builder("Paste")
+ SafetyCenterStaticEntry.Builder("OK")
.setSummary("OK")
- .setPendingIntent(
- createTestActivityRedirectPendingIntentForUser(
- deviceState.workProfile().userHandle()
- )
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
+
+ private val staticEntryUpdated: SafetyCenterStaticEntry
+ get() =
+ SafetyCenterStaticEntry.Builder("Unspecified title")
+ .setSummary("Unspecified summary")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
+
+ private fun staticEntryForWorkBuilder(
+ title: CharSequence = "Paste",
+ inQuietMode: Boolean = false
+ ) =
+ SafetyCenterStaticEntry.Builder(title)
+ .setSummary("OK")
+ .setPendingIntent(
+ createTestActivityRedirectPendingIntentForUser(
+ deviceState.workProfile().userHandle(),
+ inQuietMode
)
+ )
- private val staticEntryForWork
- get() = staticEntryForWorkBuilder.build()
+ private val staticEntryForWork: SafetyCenterStaticEntry
+ get() = staticEntryForWorkBuilder().build()
- private val staticEntryForWorkPaused
+ private val staticEntryForWorkPaused: SafetyCenterStaticEntry
get() =
- staticEntryForWorkBuilder
- // TODO(b/233188021): This needs to use the Enterprise API to override the "work"
- // keyword.
- .setSummary(safetyCenterResourcesContext.getStringByName("work_profile_paused"))
+ staticEntryForWorkBuilder(inQuietMode = true)
+ .setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
.build()
- private val staticEntryForWorkUpdated =
- SafetyCenterStaticEntry.Builder("Unspecified title for Work")
- .setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
+ private val staticEntryForWorkPausedUpdated
+ get() =
+ staticEntryForWorkBuilder(title = "Unspecified title for Work", inQuietMode = true)
+ .setSummary(safetyCenterResourcesApk.getStringByName("work_profile_paused"))
+ .build()
+
+ private val staticEntryForWorkUpdated: SafetyCenterStaticEntry
+ get() =
+ SafetyCenterStaticEntry.Builder("Unspecified title for Work")
+ .setSummary("Unspecified summary")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
private val safetyCenterDataForAdditionalUser
get() =
@@ -298,34 +337,26 @@ class SafetyCenterMultiUsersTest {
emptyList()
)
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2)
+ val safetyCenterTestRule =
+ SafetyCenterTestRule(safetyCenterTestHelper, withNotifications = true)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
+ fun setRefreshTimeoutsBeforeTest() {
+ SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
}
@After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- resetQuietMode()
+ fun resetQuietModeAfterTest() {
+ setQuietMode(false)
}
@Test
@EnsureHasWorkProfile
- @Ignore
- // Tests that check the UI takes a lot of time and they might get timeout in the postsubmits.
- // TODO(b/242999951): Write this test using the APIs instead of checking the UI.
- fun launchActivity_withProfileOwner_displaysWorkPolicyInfo() {
+ fun getSafetyCenterData_withProfileOwner_hasWorkPolicyInfo() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.workPolicyInfoConfig)
findWorkPolicyInfo()
@@ -333,10 +364,7 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasDeviceOwner
- @Ignore
- // Tests that check the UI takes a lot of time and they might get timeout in the postsubmits.
- // TODO(b/242999951): Write this test using the APIs instead of checking the UI.
- fun launchActivity_withDeviceOwner_displaysWorkPolicyInfo() {
+ fun getSafetyCenterData_withDeviceOwner_hasWorkPolicyInfo() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.workPolicyInfoConfig)
findWorkPolicyInfo()
@@ -344,21 +372,24 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasWorkProfile
- @Ignore
- // Tests that check the UI takes a lot of time and they might get timeout in the postsubmits.
- // TODO(b/242999951): Write this test using the APIs instead of checking the UI.
- fun launchActivity_withQuietModeEnabled_shouldNotDisplayWorkPolicyInfo() {
+ fun launchActivity_withQuietModeEnabled_hasWorkPolicyInfo() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.workPolicyInfoConfig)
- findWorkPolicyInfo()
setQuietMode(true)
+
+ findWorkPolicyInfo()
+ }
+
+ @Test
+ @EnsureHasNoWorkProfile
+ @EnsureHasNoDeviceOwner
+ fun launchActivity_withoutWorkProfileOrDeviceOwner_doesntHaveWorkPolicyInfo() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.workPolicyInfoConfig)
+
context.launchSafetyCenterActivity { waitAllTextNotDisplayed("Your work policy info") }
}
@Test
- @Ignore
- // Test involving toggling of quiet mode are flaky.
- // TODO(b/237365018): Re-enable them back once we figure out a way to make them stable.
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetySourceData_withQuietModeEnabled_dataIsNotCleared() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -381,7 +412,6 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
- @Postsubmit(reason = "Test takes too much time to setup")
fun getSafetySourceData_afterAdditionalUserRemoved_returnsNull() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
val additionalUserSafetyCenterManager =
@@ -409,7 +439,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetySourceData_withoutInteractAcrossUserPermission_shouldThrowError() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -422,7 +451,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetySourceData_withoutAppInstalledForWorkProfile_shouldReturnNull() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -444,7 +472,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetySourceData_withRemovedProfile_shouldReturnNull() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -466,10 +493,7 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
- @Ignore
- // Test involving toggling of quiet mode are flaky.
fun getSafetySourceData_withProfileInQuietMode_shouldReturnData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
val managedSafetyCenterManager =
@@ -490,7 +514,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasNoWorkProfile
fun getSafetyCenterData_withComplexConfigWithoutWorkProfile_returnsPrimaryDataFromConfig() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexAllProfileConfig)
@@ -506,9 +529,7 @@ class SafetyCenterMultiUsersTest {
SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
.setSummary(
- safetyCenterResourcesContext.getStringByName(
- "group_unknown_summary"
- )
+ safetyCenterResourcesApk.getStringByName("group_unknown_summary")
)
.setEntries(listOf(dynamicBareboneDefault, dynamicDisabledDefault))
.setSeverityUnspecifiedIconType(
@@ -528,7 +549,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetyCenterData_withComplexConfigWithoutDataProvided_returnsDataFromConfig() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexAllProfileConfig)
@@ -544,9 +564,7 @@ class SafetyCenterMultiUsersTest {
SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
.setSummary(
- safetyCenterResourcesContext.getStringByName(
- "group_unknown_summary"
- )
+ safetyCenterResourcesApk.getStringByName("group_unknown_summary")
)
.setEntries(
listOf(
@@ -579,7 +597,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetyCenterData_withComplexConfigWithPrimaryDataProvided_returnsPrimaryDataProvided() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexAllProfileConfig)
@@ -633,7 +650,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetyCenterData_withComplexConfigWithAllDataProvided_returnsAllDataProvided() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexAllProfileConfig)
@@ -744,15 +760,12 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
- @Ignore
- // Test involving toggling of quiet mode are flaky.
- // TODO(b/237365018): Re-enable them back once we figure out a way to make them stable.
fun getSafetyCenterData_withQuietMode_shouldHaveWorkProfilePausedSummaryAndNoWorkIssues() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.complexAllProfileConfig)
updatePrimaryProfileSources()
updateWorkProfileSources()
-
setQuietMode(true)
+
val apiSafetyCenterData = safetyCenterManager.getSafetyCenterDataWithPermission()
val safetyCenterDataFromComplexConfig =
@@ -768,8 +781,9 @@ class SafetyCenterMultiUsersTest {
listOf(
dynamicBareboneUpdated,
dynamicDisabledUpdated,
- dynamicDisabledForWorkPaused,
- dynamicHiddenUpdated
+ dynamicDisabledForWorkPausedUpdated,
+ dynamicHiddenUpdated,
+ dynamicHiddenForWorkPausedUpdated,
)
)
.setSeverityUnspecifiedIconType(
@@ -794,7 +808,7 @@ class SafetyCenterMultiUsersTest {
"OK",
listOf(
staticEntryUpdated,
- staticEntryForWorkPaused,
+ staticEntryForWorkPausedUpdated,
staticEntry,
staticEntryForWorkPaused
)
@@ -807,7 +821,6 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
- @Postsubmit(reason = "Test takes too much time to setup")
fun getSafetyCenterData_withDataForDifferentUserProfileGroup_shouldBeUnaffected() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
val dataForPrimaryUser = safetySourceTestData.information
@@ -830,7 +843,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Ignore // Removing a managed profile causes a refresh, which makes some tests flaky.
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun getSafetyCenterData_afterManagedProfileRemoved_returnsDefaultData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -845,9 +857,7 @@ class SafetyCenterMultiUsersTest {
SafetyCenterEntryGroup.Builder(SINGLE_SOURCE_GROUP_ID, "OK")
.setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
.setSummary(
- safetyCenterResourcesContext.getStringByName(
- "group_unknown_summary"
- )
+ safetyCenterResourcesApk.getStringByName("group_unknown_summary")
)
.setEntries(
listOf(
@@ -905,7 +915,6 @@ class SafetyCenterMultiUsersTest {
@Test
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
- @Postsubmit(reason = "Test takes too much time to setup")
fun getSafetyCenterData_afterAdditionalUserRemoved_returnsDefaultData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
val additionalUserSafetyCenterManager =
@@ -926,7 +935,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_primaryProfileIssueOnlySource_shouldNotBeAbleToSetDataToWorkProfile() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
@@ -944,7 +952,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_withoutInteractAcrossUserPermission_shouldThrowError() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -962,7 +969,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_withoutAppInstalledForWorkProfile_shouldNoOp() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -984,7 +990,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_withRemovedProfile_shouldNoOp() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -1006,7 +1011,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasCloneProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_withUnsupportedProfile_shouldNoOp() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -1027,10 +1031,7 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
- @Ignore
- // Test involving toggling of quiet mode are flaky.
fun setSafetySourceData_withProfileInQuietMode_shouldSetData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
val dataForWork = safetySourceTestData.informationWithIssueForWork
@@ -1051,7 +1052,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_issuesOnlySourceWithWorkProfile_shouldBeAbleToSetData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceAllProfileConfig)
@@ -1079,7 +1079,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_primaryProfileSource_shouldNotBeAbleToSetDataToWorkProfile() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -1096,7 +1095,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasWorkProfile(installInstrumentedApp = TRUE)
fun setSafetySourceData_sourceWithWorkProfile_shouldBeAbleToSetData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
@@ -1122,7 +1120,32 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
+ @EnsureHasWorkProfile(installInstrumentedApp = TRUE)
+ fun setSafetySourceData_notificationsAllowed_workProfile_sendsNotification() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceAllProfileConfig)
+ SafetyCenterFlags.notificationsEnabled = true
+ SafetyCenterFlags.notificationsAllowedSources = setOf(SINGLE_SOURCE_ALL_PROFILE_ID)
+ SafetyCenterFlags.immediateNotificationBehaviorIssues =
+ setOf("$SINGLE_SOURCE_ALL_PROFILE_ID/$ISSUE_TYPE_ID")
+ val dataForWork = safetySourceTestData.informationWithIssueForWork
+ val managedSafetyCenterManager =
+ getSafetyCenterManagerForUser(deviceState.workProfile().userHandle())
+
+ managedSafetyCenterManager.setSafetySourceDataWithInteractAcrossUsersPermission(
+ SINGLE_SOURCE_ALL_PROFILE_ID,
+ dataForWork
+ )
+
+ TestNotificationListener.waitForNotificationsMatching(
+ NotificationCharacteristics(
+ title = "Information issue title",
+ text = "Information issue summary",
+ actions = listOf("Review")
+ )
+ )
+ }
+
+ @Test
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
fun setSafetySourceData_forStoppedUser_shouldSetData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -1144,7 +1167,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
fun setSafetySourceData_forBothPrimaryAdditionalUser_shouldSetData() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -1170,7 +1192,6 @@ class SafetyCenterMultiUsersTest {
}
@Test
- @Postsubmit(reason = "Test takes too much time to setup")
@EnsureHasAdditionalUser(installInstrumentedApp = TRUE)
fun setSafetySourceData_forAdditionalUser_shouldNotAffectDataForPrimaryUser() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -1190,8 +1211,6 @@ class SafetyCenterMultiUsersTest {
private fun findWorkPolicyInfo() {
context.launchSafetyCenterActivity {
- // TODO(b/233188021): This needs to use the Enterprise API to override the "work"
- // keyword.
waitAllTextDisplayed("Your work policy info", "Settings managed by your IT admin")
}
}
@@ -1207,11 +1226,15 @@ class SafetyCenterMultiUsersTest {
}
}
- private fun createTestActivityRedirectPendingIntentForUser(user: UserHandle): PendingIntent {
+ private fun createTestActivityRedirectPendingIntentForUser(
+ user: UserHandle,
+ inQuietMode: Boolean = false
+ ): PendingIntent {
return callWithShellPermissionIdentity(INTERACT_ACROSS_USERS) {
SafetySourceTestData.createRedirectPendingIntent(
getContextForUser(user),
- Intent(ACTION_TEST_ACTIVITY)
+ Intent(ACTION_TEST_ACTIVITY),
+ inQuietMode
)
}
}
@@ -1238,16 +1261,23 @@ class SafetyCenterMultiUsersTest {
getSafetyCenterDataWithPermission()
}
- private fun setQuietMode(value: Boolean) {
- deviceState.workProfile().setQuietMode(value)
- inQuietMode = value
- }
-
- private fun resetQuietMode() {
- if (!inQuietMode) {
+ private fun setQuietMode(enableQuietMode: Boolean) {
+ if (inQuietMode == enableQuietMode) {
return
}
- setQuietMode(false)
+ if (enableQuietMode) {
+ deviceState.workProfile().setQuietMode(true)
+ } else {
+ // This is needed to ensure the refresh broadcast doesn't leak onto other tests.
+ disableQuietModeAndWaitForRefreshToComplete()
+ }
+ inQuietMode = enableQuietMode
+ }
+
+ private fun disableQuietModeAndWaitForRefreshToComplete() {
+ val listener = safetyCenterTestHelper.addListener()
+ deviceState.workProfile().setQuietMode(false)
+ listener.waitForSafetyCenterRefresh()
}
private fun safetyCenterEntryOkForWork(sourceId: String, managedUserId: Int) =
diff --git a/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml b/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
index 5357ed4f7..a1826653f 100644
--- a/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
+++ b/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
@@ -43,9 +43,12 @@
aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
<option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/functional/safetycenter/safetycenteractivity/TEST_MAPPING b/tests/functional/safetycenter/safetycenteractivity/TEST_MAPPING
index 533b4d2a5..dcc2f817f 100644
--- a/tests/functional/safetycenter/safetycenteractivity/TEST_MAPPING
+++ b/tests/functional/safetycenter/safetycenteractivity/TEST_MAPPING
@@ -9,7 +9,7 @@
"name": "SafetyCenterActivityFunctionalTestCases[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
diff --git a/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt b/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
index 2d4dd2a8c..73c33f904 100644
--- a/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
+++ b/tests/functional/safetycenter/safetycenteractivity/src/android/safetycenter/functional/ui/SafetyCenterActivityTest.kt
@@ -17,7 +17,7 @@
package android.safetycenter.functional.ui
import android.content.Context
-import android.os.Build.VERSION.CODENAME
+import android.os.Build
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.Bundle
@@ -37,7 +37,6 @@ import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ISSUE_ONLY_ALL_OPTIONAL_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
@@ -47,12 +46,15 @@ import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_4
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_5
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
import com.android.safetycenter.testing.SafetySourceTestData
import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID
import com.android.safetycenter.testing.SafetySourceTestData.Companion.RECOMMENDATION_ISSUE_ID
+import com.android.safetycenter.testing.SettingsPackage.getSettingsPackageName
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.MORE_ISSUES_LABEL
import com.android.safetycenter.testing.UiTestHelper.RESCAN_BUTTON_LABEL
import com.android.safetycenter.testing.UiTestHelper.clickConfirmDismissal
@@ -67,13 +69,12 @@ import com.android.safetycenter.testing.UiTestHelper.waitButtonDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitCollapsedIssuesDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitExpandedIssuesDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceDataDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueNotDisplayed
import org.junit.After
-import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -82,38 +83,18 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterActivityTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = getApplicationContext()
-
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
- // JUnit's Assume is not supported in @BeforeClass by the tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@After
fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
getUiDevice().resetRotation()
}
@@ -549,7 +530,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_withAttribution_hasProperContentDescriptions() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -722,7 +703,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_resolveIssue_withDialogClickYes_resolves() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(
@@ -748,7 +729,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_resolveIssue_withDialog_rotates_clickYes_resolves() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(
@@ -778,7 +759,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_resolveIssue_withDialogClicksNo_cancels() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(
@@ -880,7 +861,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_withAttributionTitleSetBySource_displaysAttributionTitle() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -891,7 +872,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_attributionNotSetBySource_displaysGroupTitleAsAttribution() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -902,7 +883,7 @@ class SafetyCenterActivityTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun issueCard_attributionNotSetBySourceAndGroupTitleNull_doesNotDisplayAttributionTitle() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceNoGroupTitleConfig)
@@ -915,9 +896,6 @@ class SafetyCenterActivityTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
fun issueCard_attributionNotSetBySourceOnTiramisu_doesNotDisplayAttributionTitle() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(CODENAME == "UpsideDownCake")
- assumeFalse(CODENAME == "VanillaIceCream")
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val data = safetySourceTestData.recommendationWithGeneralIssue
@@ -1127,18 +1105,14 @@ class SafetyCenterActivityTest {
context.launchSafetyCenterActivity {
clickMoreIssuesCard()
- val uiDevice = getUiDevice()
- uiDevice.waitForIdle()
-
- // Verify cards initially expanded
- waitExpandedIssuesDisplayed(
- safetySourceTestData.criticalResolvingGeneralIssue,
- safetySourceTestData.recommendationGeneralIssue,
- safetySourceTestData.informationIssue
- )
+ // Not checking that all the cards are correctly expanded here, as it is already covered
+ // by other tests and makes this tests too slow otherwise. See b/288381777.
+ // We still check that the middle card title is displayed though, as this helps ensure
+ // the expansion did go through.
+ waitAllTextDisplayed(safetySourceTestData.recommendationGeneralIssue.title)
// Device rotation to trigger usage of savedinstancestate via config update
- uiDevice.rotate()
+ getUiDevice().rotate()
// Verify cards remain expanded
waitExpandedIssuesDisplayed(
@@ -1150,7 +1124,7 @@ class SafetyCenterActivityTest {
}
@Test
- fun moreIssuesCard_twoIssuesAlreadyShown_expandAdditionalIssueCards() {
+ fun moreIssuesCard_withThreeIssues_showsTopIssuesAndMoreIssuesCard() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
safetyCenterTestHelper.setData(
SOURCE_ID_1,
@@ -1170,14 +1144,31 @@ class SafetyCenterActivityTest {
waitSourceIssueDisplayed(safetySourceTestData.recommendationGeneralIssue)
waitAllTextDisplayed(MORE_ISSUES_LABEL)
waitSourceIssueNotDisplayed(safetySourceTestData.informationIssue)
+ }
+ }
+
+ @Test
+ fun moreIssuesCard_twoIssuesAlreadyShown_expandAdditionalIssueCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
+ safetyCenterTestHelper.setData(
+ SOURCE_ID_1,
+ safetySourceTestData.criticalWithResolvingGeneralIssue
+ )
+ safetyCenterTestHelper.setData(
+ SOURCE_ID_2,
+ safetySourceTestData.recommendationWithGeneralIssue
+ )
+ safetyCenterTestHelper.setData(SOURCE_ID_3, safetySourceTestData.informationWithIssue)
+
+ val bundle = Bundle()
+ bundle.putString(EXTRA_SAFETY_SOURCE_ID, SOURCE_ID_2)
+ bundle.putString(EXTRA_SAFETY_SOURCE_ISSUE_ID, RECOMMENDATION_ISSUE_ID)
+ context.launchSafetyCenterActivity(bundle) {
+ waitSourceIssueNotDisplayed(safetySourceTestData.informationIssue)
clickMoreIssuesCard()
- waitExpandedIssuesDisplayed(
- safetySourceTestData.criticalResolvingGeneralIssue,
- safetySourceTestData.recommendationGeneralIssue,
- safetySourceTestData.informationIssue
- )
+ waitSourceIssueDisplayed(safetySourceTestData.informationIssue)
}
}
@@ -1417,10 +1408,6 @@ class SafetyCenterActivityTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
fun launchSafetyCenter_enableSubpagesFlagOnT_stillShowsExpandAndCollapseEntries() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(CODENAME == "UpsideDownCake")
- assumeFalse(CODENAME == "VanillaIceCream")
-
SafetyCenterFlags.showSubpages = true
val sourceTestData = safetySourceTestData.information
val config = safetyCenterTestConfigs.multipleSourceGroupsConfig
@@ -1474,17 +1461,40 @@ class SafetyCenterActivityTest {
}
}
- companion object {
- private const val EXPAND_ISSUE_GROUP_QS_FRAGMENT_KEY = "expand_issue_group_qs_fragment_key"
- private const val SAFETY_SOURCE_1_TITLE = "Safety Source 1 Title"
- private const val SAFETY_SOURCE_1_SUMMARY = "Safety Source 1 Summary"
- private const val SAFETY_SOURCE_2_TITLE = "Safety Source 2 Title"
- private const val SAFETY_SOURCE_2_SUMMARY = "Safety Source 2 Summary"
- private const val SAFETY_SOURCE_3_TITLE = "Safety Source 3 Title"
- private const val SAFETY_SOURCE_3_SUMMARY = "Safety Source 3 Summary"
- private const val SAFETY_SOURCE_4_TITLE = "Safety Source 4 Title"
- private const val SAFETY_SOURCE_4_SUMMARY = "Safety Source 4 Summary"
- private const val SAFETY_SOURCE_5_TITLE = "Safety Source 5 Title"
- private const val SAFETY_SOURCE_5_SUMMARY = "Safety Source 5 Summary"
+ @Test
+ fun launchActivity_openWithPrivacyControlsIntent_showsPrivacyControls() {
+ context.launchSafetyCenterActivity(intentAction = PRIVACY_CONTROLS_ACTION) {
+ waitPageTitleDisplayed("Privacy controls")
+ }
+ }
+
+ @Test
+ fun launchActivity_openWithPrivacyControlsIntentWithScDisabled_showsLegacyPrivacyPage() {
+ // This test should technically run on T+ but we have to restrict it to V+ as b/286690307 is
+ // causing a flake which was only fixed on master.
+ assumeTrue(
+ Build.VERSION.SDK_INT > UPSIDE_DOWN_CAKE || Build.VERSION.CODENAME == "VanillaIceCream"
+ )
+ safetyCenterTestHelper.setEnabled(false)
+
+ context.launchSafetyCenterActivity(intentAction = PRIVACY_CONTROLS_ACTION) {
+ waitDisplayed(By.pkg(context.getSettingsPackageName()))
+ waitPageTitleDisplayed("Privacy")
+ }
+ }
+
+ private companion object {
+ const val EXPAND_ISSUE_GROUP_QS_FRAGMENT_KEY = "expand_issue_group_qs_fragment_key"
+ const val SAFETY_SOURCE_1_TITLE = "Safety Source 1 Title"
+ const val SAFETY_SOURCE_1_SUMMARY = "Safety Source 1 Summary"
+ const val SAFETY_SOURCE_2_TITLE = "Safety Source 2 Title"
+ const val SAFETY_SOURCE_2_SUMMARY = "Safety Source 2 Summary"
+ const val SAFETY_SOURCE_3_TITLE = "Safety Source 3 Title"
+ const val SAFETY_SOURCE_3_SUMMARY = "Safety Source 3 Summary"
+ const val SAFETY_SOURCE_4_TITLE = "Safety Source 4 Title"
+ const val SAFETY_SOURCE_4_SUMMARY = "Safety Source 4 Summary"
+ const val SAFETY_SOURCE_5_TITLE = "Safety Source 5 Title"
+ const val SAFETY_SOURCE_5_SUMMARY = "Safety Source 5 Summary"
+ const val PRIVACY_CONTROLS_ACTION = "android.settings.PRIVACY_CONTROLS"
}
}
diff --git a/tests/functional/safetycenter/singleuser/AndroidManifest.xml b/tests/functional/safetycenter/singleuser/AndroidManifest.xml
index 7ca38dede..18a3b167a 100644
--- a/tests/functional/safetycenter/singleuser/AndroidManifest.xml
+++ b/tests/functional/safetycenter/singleuser/AndroidManifest.xml
@@ -17,14 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.safetycenter.functional">
<application>
- <service android:name=".testing.TestNotificationListener"
- android:label="TestNotificationListener"
- android:exported="false"
- android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
- <intent-filter>
- <action android:name="android.service.notification.NotificationListenerService" />
- </intent-filter>
- </service>
+
<uses-library android:name="android.test.runner"/>
</application>
diff --git a/tests/functional/safetycenter/singleuser/AndroidTest.xml b/tests/functional/safetycenter/singleuser/AndroidTest.xml
index d9d5b1361..3aa173508 100644
--- a/tests/functional/safetycenter/singleuser/AndroidTest.xml
+++ b/tests/functional/safetycenter/singleuser/AndroidTest.xml
@@ -43,9 +43,12 @@
aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
<option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/tests/functional/safetycenter/singleuser/TEST_MAPPING b/tests/functional/safetycenter/singleuser/TEST_MAPPING
index 8285ecd5a..9ba98a87a 100644
--- a/tests/functional/safetycenter/singleuser/TEST_MAPPING
+++ b/tests/functional/safetycenter/singleuser/TEST_MAPPING
@@ -9,7 +9,7 @@
"name": "SafetyCenterFunctionalTestCases[com.google.android.permission.apex]",
"options": [
{
- "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
index 75d2fd57d..e2a7802b3 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterManagerTest.kt
@@ -19,7 +19,6 @@ package android.safetycenter.functional
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
-import android.os.Build
import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.UserHandle
@@ -70,17 +69,17 @@ import com.android.safetycenter.internaldata.SafetyCenterBundles
import com.android.safetycenter.internaldata.SafetyCenterBundles.ISSUES_TO_GROUPS_BUNDLE_KEY
import com.android.safetycenter.internaldata.SafetyCenterEntryId
import com.android.safetycenter.internaldata.SafetyCenterIds
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.Coroutines.waitForWithTimeout
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.dismissSafetyCenterIssueWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterConfigWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetyCenterDataWithPermission
+import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.getSafetySourceDataWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.refreshSafetySourcesWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.reportSafetySourceErrorWithPermission
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ACTION_TEST_ACTIVITY_EXPORTED
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID
@@ -116,6 +115,7 @@ import com.android.safetycenter.testing.SafetyCenterTestData.Companion.withAttri
import com.android.safetycenter.testing.SafetyCenterTestData.Companion.withDismissedIssuesIfAtLeastU
import com.android.safetycenter.testing.SafetyCenterTestData.Companion.withoutExtras
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
@@ -130,15 +130,15 @@ import com.android.safetycenter.testing.SafetySourceTestData.Companion.INFORMATI
import com.android.safetycenter.testing.SafetySourceTestData.Companion.RECOMMENDATION_ISSUE_ID
import com.android.safetycenter.testing.SettingsPackage.getSettingsPackageName
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.google.common.base.Preconditions.checkState
import com.google.common.truth.Truth.assertThat
import java.time.Duration
import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
-import org.junit.After
import org.junit.Assume.assumeFalse
import org.junit.Assume.assumeTrue
-import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -146,594 +146,628 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterManagerTest {
private val context: Context = getApplicationContext()
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestData = SafetyCenterTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- private val safetyCenterStatusOk =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_summary")
- )
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
- .build()
+ private val safetyCenterStatusOk: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_summary")
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+
+ private val safetyCenterStatusUnknownScanning: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName("scanning_title"),
+ safetyCenterResourcesApk.getStringByName("loading_summary")
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ .setRefreshStatus(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
+ .build()
+
+ private val safetyCenterStatusOkOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+
+ private val safetyCenterStatusOkReviewOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_ok_review_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+
+ private val safetyCenterStatusOkReview: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_ok_review_title"
+ ),
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_ok_review_summary"
+ )
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
+ .build()
+
+ private val safetyCenterStatusGeneralRecommendationOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_safety_recommendation_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
+ .build()
+
+ private val safetyCenterStatusAccountRecommendationOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_account_recommendation_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
+ .build()
+
+ private val safetyCenterStatusDeviceRecommendationOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_device_recommendation_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
+ .build()
- private val safetyCenterStatusUnknownScanning =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName("scanning_title"),
- safetyCenterResourcesContext.getStringByName("loading_summary")
+ private val safetyCenterStatusGeneralCriticalOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_safety_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterStatusGeneralCriticalTwoAlerts: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_safety_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(2)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterStatusAccountCriticalOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_account_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterStatusAccountCriticalTwoAlerts: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_account_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(2)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterStatusDeviceCriticalOneAlert: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_device_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(1)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterStatusDeviceCriticalTwoAlerts: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_critical_device_warning_title"
+ ),
+ safetyCenterTestData.getAlertString(2)
+ )
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .build()
+
+ private val safetyCenterEntryOrGroupRecommendation: SafetyCenterEntryOrGroup
+ get() =
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
+ )
+
+ private val safetyCenterEntryOrGroupCritical: SafetyCenterEntryOrGroup
+ get() =
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryCritical(SINGLE_SOURCE_ID)
+ )
+
+ private val safetyCenterEntryGroupMixedFromComplexConfig: SafetyCenterEntryOrGroup
+ get() =
+ SafetyCenterEntryOrGroup(
+ SafetyCenterEntryGroup.Builder(MIXED_STATEFUL_GROUP_ID, "OK")
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
+ .setSummary(safetyCenterResourcesApk.getStringByName("group_unknown_summary"))
+ .setEntries(
+ listOf(
+ safetyCenterTestData.safetyCenterEntryDefault(DYNAMIC_IN_STATEFUL_ID),
+ SafetyCenterEntry.Builder(
+ SafetyCenterTestData.entryId(STATIC_IN_STATEFUL_ID),
+ "OK"
+ )
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
+ .setSummary("OK")
+ .setPendingIntent(
+ safetySourceTestData.testActivityRedirectPendingIntent
+ )
+ .setSeverityUnspecifiedIconType(
+ SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON
+ )
+ .build()
+ )
+ )
+ .setSeverityUnspecifiedIconType(
+ SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION
+ )
+ .build()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
- .setRefreshStatus(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
- .build()
- private val safetyCenterStatusOkOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterTestData.getAlertString(1)
+ private val safetyCenterStaticEntryGroupFromComplexConfig: SafetyCenterStaticEntryGroup
+ get() =
+ SafetyCenterStaticEntryGroup(
+ "OK",
+ listOf(
+ SafetyCenterStaticEntry.Builder("OK")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build(),
+ SafetyCenterStaticEntry.Builder("OK")
+ .setSummary("OK")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
+ )
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
- .build()
- private val safetyCenterStatusOkReviewOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_title"
- ),
- safetyCenterTestData.getAlertString(1)
+ private val safetyCenterStaticEntryGroupMixedFromComplexConfig: SafetyCenterStaticEntryGroup
+ get() =
+ SafetyCenterStaticEntryGroup(
+ "OK",
+ listOf(
+ SafetyCenterStaticEntry.Builder("OK")
+ .setSummary("OK")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build(),
+ SafetyCenterStaticEntry.Builder("OK")
+ .setSummary("OK")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
+ )
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
- .build()
- private val safetyCenterStatusOkReview =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_title"
- ),
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_summary"
+ private val safetyCenterStaticEntryGroupMixedUpdatedFromComplexConfig:
+ SafetyCenterStaticEntryGroup
+ get() =
+ SafetyCenterStaticEntryGroup(
+ "OK",
+ listOf(
+ SafetyCenterStaticEntry.Builder("Unspecified title")
+ .setSummary("Unspecified summary")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build(),
+ SafetyCenterStaticEntry.Builder("OK")
+ .setSummary("OK")
+ .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
+ .build()
)
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
- .build()
- private val safetyCenterStatusGeneralRecommendationOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_safety_recommendation_title"
+ private val safetyCenterDataFromConfigScanning: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusUnknownScanning,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryDefault(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
- .build()
- private val safetyCenterStatusAccountRecommendationOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_account_recommendation_title"
+ private val safetyCenterDataFromConfig: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterTestData.safetyCenterStatusUnknown,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryDefault(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
- .build()
- private val safetyCenterStatusDeviceRecommendationOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_device_recommendation_title"
+ private val safetyCenterDataUnspecified: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOk,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryUnspecified(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_RECOMMENDATION)
- .build()
- private val safetyCenterStatusGeneralCriticalOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_safety_warning_title"
+ private val safetyCenterDataOk: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOk,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryOk(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterStatusGeneralCriticalTwoAlerts =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_safety_warning_title"
+ private val safetyCenterDataOkWithIconAction: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOk,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData
+ .safetyCenterEntryOkBuilder(SINGLE_SOURCE_ID)
+ .setIconAction(
+ ICON_ACTION_TYPE_INFO,
+ safetySourceTestData.testActivityRedirectPendingIntent
+ )
+ .build()
+ )
),
- safetyCenterTestData.getAlertString(2)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterStatusAccountCriticalOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_account_warning_title"
+ private val safetyCenterDataUnknownScanningWithError: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusUnknownScanning,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryError(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterStatusAccountCriticalTwoAlerts =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_account_warning_title"
+ private val safetyCenterDataUnknownReviewError: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterTestData.safetyCenterStatusUnknown,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryError(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(2)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterStatusDeviceCriticalOneAlert =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_device_warning_title"
+ private val safetyCenterDataOkOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOkOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueInformation(SINGLE_SOURCE_ID)),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryOk(SINGLE_SOURCE_ID)
+ )
),
- safetyCenterTestData.getAlertString(1)
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterStatusDeviceCriticalTwoAlerts =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_critical_device_warning_title"
- ),
- safetyCenterTestData.getAlertString(2)
+ private val safetyCenterDataOkReviewCriticalEntry: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOkReview,
+ emptyList(),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
)
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING)
- .build()
- private val safetyCenterEntryOrGroupRecommendation =
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
- )
+ private val safetyCenterDataOkReviewRecommendationEntry: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOkReview,
+ emptyList(),
+ listOf(safetyCenterEntryOrGroupRecommendation),
+ emptyList()
+ )
- private val safetyCenterEntryOrGroupCritical =
- SafetyCenterEntryOrGroup(safetyCenterTestData.safetyCenterEntryCritical(SINGLE_SOURCE_ID))
+ private val safetyCenterDataOkReviewOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOkReviewOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueInformation(SINGLE_SOURCE_ID)),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
+ )
- private val safetyCenterEntryGroupMixedFromComplexConfig =
- SafetyCenterEntryOrGroup(
- SafetyCenterEntryGroup.Builder(MIXED_STATEFUL_GROUP_ID, "OK")
- .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
- .setSummary(safetyCenterResourcesContext.getStringByName("group_unknown_summary"))
- .setEntries(
- listOf(
- safetyCenterTestData.safetyCenterEntryDefault(DYNAMIC_IN_STATEFUL_ID),
- SafetyCenterEntry.Builder(
- SafetyCenterTestData.entryId(STATIC_IN_STATEFUL_ID),
- "OK"
- )
- .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNSPECIFIED)
- .setSummary("OK")
- .setPendingIntent(
- safetySourceTestData.testActivityRedirectPendingIntent
- )
- .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON)
- .build()
+ private val safetyCenterDataGeneralRecommendationOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusGeneralRecommendationOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
)
- )
- .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION)
- .build()
- )
-
- private val safetyCenterStaticEntryGroupFromComplexConfig =
- SafetyCenterStaticEntryGroup(
- "OK",
- listOf(
- SafetyCenterStaticEntry.Builder("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build(),
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
+ ),
+ emptyList()
)
- )
- private val safetyCenterStaticEntryGroupMixedFromComplexConfig =
- SafetyCenterStaticEntryGroup(
- "OK",
- listOf(
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build(),
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
+ private val safetyCenterDataGeneralRecommendationAlertWithConfirmation: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusGeneralRecommendationOneAlert,
+ listOf(
+ safetyCenterTestData.safetyCenterIssueRecommendation(
+ SINGLE_SOURCE_ID,
+ confirmationDialog = true
+ )
+ ),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
+ )
+ ),
+ emptyList()
)
- )
- private val safetyCenterStaticEntryGroupMixedUpdatedFromComplexConfig =
- SafetyCenterStaticEntryGroup(
- "OK",
- listOf(
- SafetyCenterStaticEntry.Builder("Unspecified title")
- .setSummary("Unspecified summary")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build(),
- SafetyCenterStaticEntry.Builder("OK")
- .setSummary("OK")
- .setPendingIntent(safetySourceTestData.testActivityRedirectPendingIntent)
- .build()
+ private val safetyCenterDataAccountRecommendationOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusAccountRecommendationOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
+ )
+ ),
+ emptyList()
)
- )
-
- private val safetyCenterDataFromConfigScanning =
- SafetyCenterData(
- safetyCenterStatusUnknownScanning,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryDefault(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataFromConfig =
- SafetyCenterData(
- safetyCenterTestData.safetyCenterStatusUnknown,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryDefault(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataUnspecified =
- SafetyCenterData(
- safetyCenterStatusOk,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryUnspecified(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataOk =
- SafetyCenterData(
- safetyCenterStatusOk,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(safetyCenterTestData.safetyCenterEntryOk(SINGLE_SOURCE_ID))
- ),
- emptyList()
- )
-
- private val safetyCenterDataOkWithIconAction =
- SafetyCenterData(
- safetyCenterStatusOk,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData
- .safetyCenterEntryOkBuilder(SINGLE_SOURCE_ID)
- .setIconAction(
- ICON_ACTION_TYPE_INFO,
- safetySourceTestData.testActivityRedirectPendingIntent
- )
- .build()
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataUnknownScanningWithError =
- SafetyCenterData(
- safetyCenterStatusUnknownScanning,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryError(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataUnknownReviewError =
- SafetyCenterData(
- safetyCenterTestData.safetyCenterStatusUnknown,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryError(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataOkOneAlert =
- SafetyCenterData(
- safetyCenterStatusOkOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueInformation(SINGLE_SOURCE_ID)),
- listOf(
- SafetyCenterEntryOrGroup(safetyCenterTestData.safetyCenterEntryOk(SINGLE_SOURCE_ID))
- ),
- emptyList()
- )
-
- private val safetyCenterDataOkReviewCriticalEntry =
- SafetyCenterData(
- safetyCenterStatusOkReview,
- emptyList(),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
-
- private val safetyCenterDataOkReviewRecommendationEntry =
- SafetyCenterData(
- safetyCenterStatusOkReview,
- emptyList(),
- listOf(safetyCenterEntryOrGroupRecommendation),
- emptyList()
- )
-
- private val safetyCenterDataOkReviewOneAlert =
- SafetyCenterData(
- safetyCenterStatusOkReviewOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueInformation(SINGLE_SOURCE_ID)),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
-
- private val safetyCenterDataGeneralRecommendationOneAlert =
- SafetyCenterData(
- safetyCenterStatusGeneralRecommendationOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataGeneralRecommendationAlertWithConfirmation =
- SafetyCenterData(
- safetyCenterStatusGeneralRecommendationOneAlert,
- listOf(
- safetyCenterTestData.safetyCenterIssueRecommendation(
- SINGLE_SOURCE_ID,
- confirmationDialog = true
- )
- ),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataAccountRecommendationOneAlert =
- SafetyCenterData(
- safetyCenterStatusAccountRecommendationOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataDeviceRecommendationOneAlert =
- SafetyCenterData(
- safetyCenterStatusDeviceRecommendationOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
- listOf(
- SafetyCenterEntryOrGroup(
- safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
- )
- ),
- emptyList()
- )
-
- private val safetyCenterDataGeneralCriticalOneAlert =
- SafetyCenterData(
- safetyCenterStatusGeneralCriticalOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
- private val safetyCenterDataAccountCriticalOneAlert =
- SafetyCenterData(
- safetyCenterStatusAccountCriticalOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
+ private val safetyCenterDataDeviceRecommendationOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusDeviceRecommendationOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueRecommendation(SINGLE_SOURCE_ID)),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ safetyCenterTestData.safetyCenterEntryRecommendation(SINGLE_SOURCE_ID)
+ )
+ ),
+ emptyList()
+ )
- private val safetyCenterDataDeviceCriticalOneAlert =
- SafetyCenterData(
- safetyCenterStatusDeviceCriticalOneAlert,
- listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
+ private val safetyCenterDataGeneralCriticalOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusGeneralCriticalOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
+ )
- private val safetyCenterDataCriticalOneAlertInFlight =
- SafetyCenterData(
- safetyCenterStatusGeneralCriticalOneAlert,
- listOf(
- safetyCenterTestData.safetyCenterIssueCritical(
- SINGLE_SOURCE_ID,
- isActionInFlight = true
- )
- ),
- listOf(safetyCenterEntryOrGroupCritical),
- emptyList()
- )
+ private val safetyCenterDataAccountCriticalOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusAccountCriticalOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
+ )
- private val safetyCenterDataOkReviewOneDismissedAlertInFlight =
- SafetyCenterData(
- safetyCenterStatusOkReview,
- emptyList(),
+ private val safetyCenterDataDeviceCriticalOneAlert: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusDeviceCriticalOneAlert,
+ listOf(safetyCenterTestData.safetyCenterIssueCritical(SINGLE_SOURCE_ID)),
listOf(safetyCenterEntryOrGroupCritical),
emptyList()
)
- .withDismissedIssuesIfAtLeastU(
+
+ private val safetyCenterDataCriticalOneAlertInFlight: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusGeneralCriticalOneAlert,
listOf(
safetyCenterTestData.safetyCenterIssueCritical(
SINGLE_SOURCE_ID,
isActionInFlight = true
)
- )
+ ),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
)
- private val safetyCenterDataFromComplexConfig =
- SafetyCenterData(
- safetyCenterTestData.safetyCenterStatusUnknown,
- emptyList(),
- listOf(
- SafetyCenterEntryOrGroup(
- SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
- .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
- .setSummary(
- safetyCenterResourcesContext.getStringByName("group_unknown_summary")
+ private val safetyCenterDataOkReviewOneDismissedAlertInFlight: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterStatusOkReview,
+ emptyList(),
+ listOf(safetyCenterEntryOrGroupCritical),
+ emptyList()
+ )
+ .withDismissedIssuesIfAtLeastU(
+ listOf(
+ safetyCenterTestData.safetyCenterIssueCritical(
+ SINGLE_SOURCE_ID,
+ isActionInFlight = true
)
- .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .setEntries(
- listOf(
- safetyCenterTestData.safetyCenterEntryDefault(DYNAMIC_BAREBONE_ID),
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_ALL_OPTIONAL_ID)
- .setEnabled(false)
- .build(),
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_DISABLED_ID)
- .setPendingIntent(null)
- .setEnabled(false)
- .build(),
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_OTHER_PACKAGE_ID)
- .setPendingIntent(null)
- .setEnabled(false)
- .build()
+ )
+ )
+
+ private val safetyCenterDataFromComplexConfig: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterTestData.safetyCenterStatusUnknown,
+ emptyList(),
+ listOf(
+ SafetyCenterEntryOrGroup(
+ SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_UNKNOWN)
+ .setSummary(
+ safetyCenterResourcesApk.getStringByName("group_unknown_summary")
)
- )
- .build()
+ .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ .setEntries(
+ listOf(
+ safetyCenterTestData.safetyCenterEntryDefault(
+ DYNAMIC_BAREBONE_ID
+ ),
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_ALL_OPTIONAL_ID)
+ .setEnabled(false)
+ .build(),
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_DISABLED_ID)
+ .setPendingIntent(null)
+ .setEnabled(false)
+ .build(),
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_OTHER_PACKAGE_ID)
+ .setPendingIntent(null)
+ .setEnabled(false)
+ .build()
+ )
+ )
+ .build()
+ ),
+ safetyCenterEntryGroupMixedFromComplexConfig
),
- safetyCenterEntryGroupMixedFromComplexConfig
- ),
- listOf(
- safetyCenterStaticEntryGroupFromComplexConfig,
- safetyCenterStaticEntryGroupMixedFromComplexConfig
+ listOf(
+ safetyCenterStaticEntryGroupFromComplexConfig,
+ safetyCenterStaticEntryGroupMixedFromComplexConfig
+ )
)
- )
- private val safetyCenterDataFromComplexConfigUpdated =
- SafetyCenterData(
- safetyCenterTestData.safetyCenterStatusCritical(6),
- listOf(
- safetyCenterTestData.safetyCenterIssueCritical(
- DYNAMIC_BAREBONE_ID,
- groupId = DYNAMIC_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueCritical(
- ISSUE_ONLY_BAREBONE_ID,
- groupId = ISSUE_ONLY_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueRecommendation(
- DYNAMIC_DISABLED_ID,
- groupId = DYNAMIC_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueRecommendation(
- ISSUE_ONLY_ALL_OPTIONAL_ID,
- groupId = ISSUE_ONLY_GROUP_ID
- ),
- safetyCenterTestData.safetyCenterIssueInformation(
- DYNAMIC_IN_STATELESS_ID,
- groupId = MIXED_STATELESS_GROUP_ID
+ private val safetyCenterDataFromComplexConfigUpdated: SafetyCenterData
+ get() =
+ SafetyCenterData(
+ safetyCenterTestData.safetyCenterStatusCritical(6),
+ listOf(
+ safetyCenterTestData.safetyCenterIssueCritical(
+ DYNAMIC_BAREBONE_ID,
+ groupId = DYNAMIC_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueCritical(
+ ISSUE_ONLY_BAREBONE_ID,
+ groupId = ISSUE_ONLY_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueRecommendation(
+ DYNAMIC_DISABLED_ID,
+ groupId = DYNAMIC_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueRecommendation(
+ ISSUE_ONLY_ALL_OPTIONAL_ID,
+ groupId = ISSUE_ONLY_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueInformation(
+ DYNAMIC_IN_STATELESS_ID,
+ groupId = MIXED_STATELESS_GROUP_ID
+ ),
+ safetyCenterTestData.safetyCenterIssueInformation(
+ ISSUE_ONLY_IN_STATELESS_ID,
+ groupId = MIXED_STATELESS_GROUP_ID
+ )
),
- safetyCenterTestData.safetyCenterIssueInformation(
- ISSUE_ONLY_IN_STATELESS_ID,
- groupId = MIXED_STATELESS_GROUP_ID
- )
- ),
- listOf(
- SafetyCenterEntryOrGroup(
- SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
- .setSeverityLevel(ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
- .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
- .setSummary("Critical summary")
- .setEntries(
- listOf(
- safetyCenterTestData.safetyCenterEntryCritical(DYNAMIC_BAREBONE_ID),
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_ALL_OPTIONAL_ID)
- .setEnabled(false)
- .build(),
- safetyCenterTestData.safetyCenterEntryRecommendation(
- DYNAMIC_DISABLED_ID
- ),
- safetyCenterTestData.safetyCenterEntryUnspecified(
- DYNAMIC_HIDDEN_ID,
- pendingIntent = null
- ),
- safetyCenterTestData.safetyCenterEntryOk(
- DYNAMIC_HIDDEN_WITH_SEARCH_ID
- ),
- safetyCenterTestData
- .safetyCenterEntryDefaultBuilder(DYNAMIC_OTHER_PACKAGE_ID)
- .setPendingIntent(null)
- .setEnabled(false)
- .build()
+ listOf(
+ SafetyCenterEntryOrGroup(
+ SafetyCenterEntryGroup.Builder(DYNAMIC_GROUP_ID, "OK")
+ .setSeverityLevel(ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING)
+ .setSeverityUnspecifiedIconType(SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY)
+ .setSummary("Critical summary")
+ .setEntries(
+ listOf(
+ safetyCenterTestData.safetyCenterEntryCritical(
+ DYNAMIC_BAREBONE_ID
+ ),
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_ALL_OPTIONAL_ID)
+ .setEnabled(false)
+ .build(),
+ safetyCenterTestData.safetyCenterEntryRecommendation(
+ DYNAMIC_DISABLED_ID
+ ),
+ safetyCenterTestData.safetyCenterEntryUnspecified(
+ DYNAMIC_HIDDEN_ID,
+ pendingIntent = null
+ ),
+ safetyCenterTestData.safetyCenterEntryOk(
+ DYNAMIC_HIDDEN_WITH_SEARCH_ID
+ ),
+ safetyCenterTestData
+ .safetyCenterEntryDefaultBuilder(DYNAMIC_OTHER_PACKAGE_ID)
+ .setPendingIntent(null)
+ .setEnabled(false)
+ .build()
+ )
)
- )
- .build()
+ .build()
+ ),
+ safetyCenterEntryGroupMixedFromComplexConfig
),
- safetyCenterEntryGroupMixedFromComplexConfig
- ),
- listOf(
- safetyCenterStaticEntryGroupFromComplexConfig,
- safetyCenterStaticEntryGroupMixedUpdatedFromComplexConfig
+ listOf(
+ safetyCenterStaticEntryGroupFromComplexConfig,
+ safetyCenterStaticEntryGroupMixedUpdatedFromComplexConfig
+ )
)
- )
-
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
-
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_marksSafetySourceAsError() {
+ fun refreshSafetySources_timeout_marksSafetySourceAsError() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
@@ -751,9 +785,8 @@ class SafetyCenterManagerTest {
}
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_keepsShowingErrorUntilClearedBySource() {
+ fun refreshSafetySources_timeout_keepsShowingErrorUntilClearedBySource() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
@@ -781,18 +814,15 @@ class SafetyCenterManagerTest {
}
@Test
- fun refreshSafetySources_withShowEntriesOnTimeout_doesntSetErrorForBackgroundRefreshes() {
+ fun refreshSafetySources_timeout_doesntSetErrorForBackgroundRefreshes() {
SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
- SafetyCenterFlags.showErrorEntriesOnTimeout = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(REFRESH_REASON_OTHER)
- val safetyCenterBeforeTimeout = listener.receiveSafetyCenterData()
- assertThat(safetyCenterBeforeTimeout.status.refreshStatus)
- .isEqualTo(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
- val safetyCenterDataAfterTimeout = listener.receiveSafetyCenterData()
+ val safetyCenterDataAfterTimeout =
+ listener.waitForSafetyCenterRefresh(withErrorEntry = false)
assertThat(safetyCenterDataAfterTimeout).isEqualTo(safetyCenterDataFromConfig)
}
@@ -813,9 +843,9 @@ class SafetyCenterManagerTest {
val status1 = listener.receiveSafetyCenterData().status
assertThat(status1.refreshStatus).isEqualTo(REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS)
assertThat(status1.title.toString())
- .isEqualTo(safetyCenterResourcesContext.getStringByName("scanning_title"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("scanning_title"))
assertThat(status1.summary.toString())
- .isEqualTo(safetyCenterResourcesContext.getStringByName("loading_summary"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("loading_summary"))
val status2 = listener.receiveSafetyCenterData().status
assertThat(status2.refreshStatus).isEqualTo(REFRESH_STATUS_NONE)
assertThat(status2).isEqualTo(safetyCenterStatusOk)
@@ -837,9 +867,9 @@ class SafetyCenterManagerTest {
val status1 = listener.receiveSafetyCenterData().status
assertThat(status1.refreshStatus).isEqualTo(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
assertThat(status1.title.toString())
- .isEqualTo(safetyCenterResourcesContext.getStringByName("scanning_title"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("scanning_title"))
assertThat(status1.summary.toString())
- .isEqualTo(safetyCenterResourcesContext.getStringByName("loading_summary"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("loading_summary"))
val status2 = listener.receiveSafetyCenterData().status
assertThat(status2.refreshStatus).isEqualTo(REFRESH_STATUS_NONE)
assertThat(status2).isEqualTo(safetyCenterStatusOk)
@@ -863,13 +893,78 @@ class SafetyCenterManagerTest {
assertThat(status1.refreshStatus).isEqualTo(REFRESH_STATUS_DATA_FETCH_IN_PROGRESS)
assertThat(status1.title.toString()).isEqualTo(safetyCenterStatusOk.title.toString())
assertThat(status1.summary.toString())
- .isEqualTo(safetyCenterResourcesContext.getStringByName("loading_summary"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("loading_summary"))
val status2 = listener.receiveSafetyCenterData().status
assertThat(status2.refreshStatus).isEqualTo(REFRESH_STATUS_NONE)
assertThat(status2).isEqualTo(safetyCenterStatusOk)
}
@Test
+ fun refreshSafetySources_reasonPageOpen_allowedByFlag_broadcastSent() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
+ SafetyCenterFlags.overrideRefreshOnPageOpenSources = setOf(SINGLE_SOURCE_ID)
+ SafetySourceReceiver.setResponse(
+ Request.Refresh(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.informationWithIssue)
+ )
+
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN
+ )
+
+ val apiSafetySourceData =
+ safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
+ assertThat(apiSafetySourceData).isEqualTo(safetySourceTestData.informationWithIssue)
+ }
+
+ @Test
+ fun refreshSafetySources_reasonPageOpen_allowedByFlagLater_broadcastSentLater() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
+ SafetySourceReceiver.setResponse(
+ Request.Refresh(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.informationWithIssue)
+ )
+
+ assertFailsWith(TimeoutCancellationException::class) {
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN,
+ timeout = TIMEOUT_SHORT
+ )
+ }
+ val apiSafetySourceDataBeforeSettingFlag =
+ safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
+ SafetyCenterFlags.overrideRefreshOnPageOpenSources = setOf(SINGLE_SOURCE_ID)
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN
+ )
+ val apiSafetySourceDataAfterSettingFlag =
+ safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
+
+ assertThat(apiSafetySourceDataBeforeSettingFlag).isEqualTo(safetySourceTestData.information)
+ assertThat(apiSafetySourceDataAfterSettingFlag)
+ .isEqualTo(safetySourceTestData.informationWithIssue)
+ }
+
+ @Test
+ fun refreshSafetySources_reasonPageOpen_noDataForSource_broadcastSent() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.noPageOpenConfig)
+ SafetySourceReceiver.setResponse(
+ Request.Refresh(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.information)
+ )
+
+ safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
+ REFRESH_REASON_PAGE_OPEN
+ )
+
+ val apiSafetySourceData =
+ safetyCenterManager.getSafetySourceDataWithPermission(SINGLE_SOURCE_ID)
+ assertThat(apiSafetySourceData).isEqualTo(safetySourceTestData.information)
+ }
+
+ @Test
fun getSafetyCenterData_withoutDataProvided_returnsDataFromConfig() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
@@ -945,7 +1040,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_attributionTitleProvidedBySource_returnsIssueWithAttributionTitle() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(
@@ -961,7 +1056,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_attributionTitleNotProvided_returnsGroupTitleAsAttributionTitle() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
@@ -974,7 +1069,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_attributionNotSetAndGroupTitleNull_returnsNullAttributionTitle() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceNoGroupTitleConfig)
safetyCenterTestHelper.setData(
@@ -1002,9 +1097,6 @@ class SafetyCenterManagerTest {
@Test
@SdkSuppress(maxSdkVersion = TIRAMISU)
fun getSafetyCenterData_attributionNotSetBySourceOnTiramisu_returnsNullAttributionTitle() {
- // TODO(b/258228790): Remove after U is no longer in pre-release
- assumeFalse(Build.VERSION.CODENAME == "UpsideDownCake")
- assumeFalse(Build.VERSION.CODENAME == "VanillaIceCream")
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
@@ -1079,7 +1171,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withActionConfirmation_returnsRecommendationWithActionConfirmation() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
safetyCenterTestHelper.setData(
@@ -1159,7 +1251,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withRecommendationDataIssue_returnsDataRecommendationStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1184,7 +1276,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withCriticalDataIssue_returnsDataCriticalStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1209,7 +1301,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withRecommendationPasswordsIssue_returnsDataRecommendationStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1234,7 +1326,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withCriticalPasswordsIssue_returnsDataCriticalStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1259,7 +1351,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withRecommendationPersonalIssue_returnsDataRecommendationStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1284,7 +1376,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withCriticalPersonalIssue_returnsDataCriticalStatus() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1309,7 +1401,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusTipFirstIssueSingleTip_infoStatusWithTipSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1329,7 +1421,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusTipFirstIssueMultiTips_infoStatusWithTipsSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1365,7 +1457,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusActionFirstIssueSingleAction_infoStatusWithActionSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1385,7 +1477,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusActionFirstIssueMultiActions_infoStatusWithActionsSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1421,7 +1513,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusManualFirstIssueSingleManual_infoStatusWithAlertSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1447,7 +1539,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_infoStatusManualFirstIssueMultiManual_infoStatusWithAlertsSummary() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.issueOnlySourceConfig)
safetyCenterTestHelper.setData(
@@ -1485,7 +1577,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_withStaticEntryGroups_hasStaticEntriesToIdsMapping() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.staticSourcesConfig)
@@ -1565,7 +1657,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesOfSameSeverities_issueOfFirstSourceInConfigShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1597,7 +1689,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesInDifferentSourceGroups_topIssueRelevantForBothGroups() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1627,7 +1719,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesInSameSourceGroups_topIssueRelevantForThatGroup() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1657,7 +1749,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_noDuplicateIssues_noGroupBelongingSpecified() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1685,7 +1777,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_differentDuplicationId_bothIssuesShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1722,7 +1814,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_differentDuplicationGroup_bothIssuesShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1759,7 +1851,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_threeDuplicateIssues_onlyOneIssueShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1798,7 +1890,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesOfDifferentSeverities_moreSevereIssueShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1830,7 +1922,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_multipleDuplicationsOfIssues_correctlyDeduplicated() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1906,7 +1998,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesBothDismissed_topOneShownAsDismissed() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1947,7 +2039,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesLowerSeverityOneDismissed_topOneShown() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -1985,7 +2077,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesHigherSeverityOneDismissed_topOneShownAsDismissed() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -2023,7 +2115,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_dupIssuesLowerPrioritySameSeverityOneDismissed_topShownAsDismissed() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -2061,7 +2153,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_dupIssuesTopOneDismissedThenDisappears_bottomOneReemergesTimely() {
SafetyCenterFlags.tempHiddenIssueResurfaceDelay = Duration.ZERO
SafetyCenterFlags.resurfaceIssueMaxCounts = mapOf(SEVERITY_LEVEL_CRITICAL_WARNING to 99L)
@@ -2115,7 +2207,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_dupsOfDiffSeveritiesTopOneDismissedThenGone_bottomOneReemergesTimely() {
SafetyCenterFlags.tempHiddenIssueResurfaceDelay = Duration.ZERO
SafetyCenterFlags.resurfaceIssueMaxCounts =
@@ -2178,7 +2270,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesLowerOneResurfaces_lowerOneStillFilteredOut() {
SafetyCenterFlags.resurfaceIssueMaxCounts =
mapOf(
@@ -2241,7 +2333,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_duplicateIssuesTopOneResurfaces_topOneShown() {
SafetyCenterFlags.resurfaceIssueMaxCounts =
mapOf(
@@ -2302,7 +2394,7 @@ class SafetyCenterManagerTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun getSafetyCenterData_dupIssuesTopOneResolved_bottomOneReemergesAfterTemporaryHiddenPeriod() {
SafetyCenterFlags.tempHiddenIssueResurfaceDelay = RESURFACE_DELAY
safetyCenterTestHelper.setConfig(
@@ -2836,7 +2928,7 @@ class SafetyCenterManagerTest {
safetyCenterManager.getSafetyCenterDataWithPermission().getGroup(SUMMARY_TEST_GROUP_ID)
assertThat(group.summary)
- .isEqualTo(safetyCenterResourcesContext.getStringByName("group_unknown_summary"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("group_unknown_summary"))
assertThat(group.severityLevel).isEqualTo(ENTRY_SEVERITY_LEVEL_UNKNOWN)
}
@@ -2850,7 +2942,7 @@ class SafetyCenterManagerTest {
.getGroup(ANDROID_LOCK_SCREEN_SOURCES_GROUP_ID)
assertThat(initialGroup.summary)
- .isEqualTo(safetyCenterResourcesContext.getStringByName("group_unknown_summary"))
+ .isEqualTo(safetyCenterResourcesApk.getStringByName("group_unknown_summary"))
assertThat(initialGroup.severityLevel).isEqualTo(ENTRY_SEVERITY_LEVEL_UNKNOWN)
safetyCenterTestHelper.setData(DYNAMIC_BAREBONE_ID, safetySourceTestData.unspecified)
@@ -3345,7 +3437,7 @@ class SafetyCenterManagerTest {
assertThat(error)
.isEqualTo(
SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("resolving_action_error")
+ safetyCenterResourcesApk.getStringByName("resolving_action_error")
)
)
}
@@ -3379,7 +3471,7 @@ class SafetyCenterManagerTest {
assertThat(error)
.isEqualTo(
SafetyCenterErrorDetails(
- safetyCenterResourcesContext.getStringByName("resolving_action_error")
+ safetyCenterResourcesApk.getStringByName("resolving_action_error")
)
)
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
index 70d6468fa..20802dd2f 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterNotificationTest.kt
@@ -28,19 +28,21 @@ import android.safetycenter.SafetyCenterStatus
import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceErrorDetails
import android.safetycenter.SafetySourceIssue
-import android.safetycenter.functional.testing.NotificationCharacteristics
-import android.safetycenter.functional.testing.TestNotificationListener
+import android.service.notification.StatusBarNotification
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.DisableAnimationRule
+import com.android.compatibility.common.util.FreezeRotationRule
import com.android.safetycenter.pendingintents.PendingIntentSender
+import com.android.safetycenter.testing.Coroutines
import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
+import com.android.safetycenter.testing.NotificationCharacteristics
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.executeBlockAndExit
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.clearAllSafetySourceDataForTestsWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.dismissSafetyCenterIssueWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.reportSafetySourceErrorWithPermission
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_1
@@ -48,20 +50,23 @@ import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_5
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
import com.android.safetycenter.testing.SafetySourceTestData
import com.android.safetycenter.testing.SafetySourceTestData.Companion.ISSUE_TYPE_ID
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.StatusBarNotificationWithChannel
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
+import com.android.safetycenter.testing.TestNotificationListener
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueDisplayed
import com.google.common.truth.Truth.assertThat
import java.time.Duration
import kotlin.test.assertFailsWith
import kotlinx.coroutines.TimeoutCancellationException
-import org.junit.After
-import org.junit.Assume.assumeTrue
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -74,41 +79,23 @@ class SafetyCenterNotificationTest {
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager =
requireNotNull(context.getSystemService(SafetyCenterManager::class.java)) {
- "Could not get system service"
+ "Could not get SafetyCenterManager"
}
- // JUnit's Assume is not supported in @BeforeClass by the CTS tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2)
+ val safetyCenterTestRule =
+ SafetyCenterTestRule(safetyCenterTestHelper, withNotifications = true)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun setUp() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- TestNotificationListener.setup()
+ fun enableNotificationsForTestSourceBeforeTest() {
SafetyCenterFlags.notificationsEnabled = true
setFlagsForImmediateNotifications(SINGLE_SOURCE_ID)
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
}
- @After
- fun tearDown() {
- if (!shouldRunTests) {
- return
- }
- // It is important to reset the notification listener last because it waits/ensures that
- // all notifications have been removed before returning.
- safetyCenterTestHelper.reset()
- TestNotificationListener.reset()
- }
-
@Test
fun setSafetySourceData_withNoIssue_noNotification() {
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.information)
@@ -153,7 +140,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationBehaviorNever_noNotification() {
val data =
safetySourceTestData
@@ -172,7 +159,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationBehaviorDelay_noImmediateNotification() {
SafetyCenterFlags.notificationsMinDelay = Duration.ofDays(1)
val data =
@@ -192,7 +179,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationBehaviorDelay_sendsNotificationAfterDelay() {
SafetyCenterFlags.notificationsMinDelay = Duration.ofDays(1)
val delayedNotificationIssue =
@@ -237,7 +224,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationBehaviorDelayOfZero_sendsNotificationImmediately() {
SafetyCenterFlags.immediateNotificationBehaviorIssues = emptySet()
SafetyCenterFlags.notificationsMinDelay = Duration.ofSeconds(0)
@@ -264,7 +251,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationBehaviorImmediately_sendsNotification() {
SafetyCenterFlags.immediateNotificationBehaviorIssues = emptySet()
val data =
@@ -341,7 +328,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withNotificationsAllowedForSourceByConfig_sendsNotification() {
SafetyCenterFlags.notificationsAllowedSources = emptySet()
SafetyCenterFlags.immediateNotificationBehaviorIssues = emptySet()
@@ -372,7 +359,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withCustomNotification_usesCustomValues() {
val intent1 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "1")
val intent2 = safetySourceTestData.testActivityRedirectPendingIntent(identifier = "2")
@@ -418,7 +405,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_withEmptyCustomActions_notificationHasNoActions() {
val notification =
SafetySourceIssue.Notification.Builder("Custom title", "Custom text")
@@ -539,6 +526,22 @@ class SafetyCenterNotificationTest {
TestNotificationListener.waitForZeroNotifications()
}
+ // TODO(b/284271124): Decide what to do with existing notifications when flag flipped off
+ @Test
+ fun setSafetySourceData_removingAnIssue_afterFlagTurnedOff_noNotificationChanges() {
+ val data1 = safetySourceTestData.recommendationWithAccountIssue
+ val data2 = safetySourceTestData.information
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, data1)
+
+ TestNotificationListener.waitForSingleNotification()
+
+ SafetyCenterFlags.notificationsEnabled = false
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, data2)
+
+ TestNotificationListener.waitForZeroNotificationEvents()
+ }
+
@Test
fun reportSafetySourceError_sourceWithNotification_cancelsNotification() {
val data = safetySourceTestData.recommendationWithAccountIssue
@@ -630,7 +633,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_duplicateIssues_sendsOneNotification() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -660,7 +663,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun setSafetySourceData_duplicateIssueOfLowerSeverityDismissed_sendsNotification() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -784,7 +787,7 @@ class SafetyCenterNotificationTest {
}
@Test
- @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
fun dismissingNotification_withDuplicateIssues_allDismissed() {
safetyCenterTestHelper.setConfig(
safetyCenterTestConfigs.multipleSourcesWithDeduplicationInfoConfig
@@ -898,13 +901,135 @@ class SafetyCenterNotificationTest {
sendActionPendingIntentAndWaitWithPermission(action)
- TestNotificationListener.waitForSingleNotificationMatching(
- NotificationCharacteristics(
- "Issue solved",
- "",
- actions = emptyList(),
+ TestNotificationListener.waitForSuccessNotification("Issue solved")
+ }
+
+ @Test
+ fun successNotification_notificationHasAutoCancel() {
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.criticalWithResolvingIssueWithSuccessMessage
+ )
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+ val action =
+ notificationWithChannel.statusBarNotification.notification.actions.firstOrNull()
+ checkNotNull(action) { "Notification action unexpectedly null" }
+ SafetySourceReceiver.setResponse(
+ Request.ResolveAction(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.information)
+ )
+ sendActionPendingIntentAndWaitWithPermission(action)
+
+ TestNotificationListener.waitForSuccessNotification("Issue solved") {
+ assertThat(it.hasAutoCancel()).isTrue()
+ }
+ }
+
+ // TODO(b/284271124): Decide what to do with existing notifications when flag flipped off
+ @Test
+ fun sendActionPendingIntent_flagDisabled_pendingIntentNotSentToSource() {
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.criticalWithResolvingIssueWithSuccessMessage
+ )
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+ val action =
+ notificationWithChannel.statusBarNotification.notification.actions.firstOrNull()
+ checkNotNull(action) { "Notification action unexpectedly null" }
+ SafetySourceReceiver.setResponse(
+ Request.ResolveAction(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.information)
+ )
+ SafetyCenterFlags.notificationsEnabled = false
+
+ assertFailsWith(TimeoutCancellationException::class) {
+ sendActionPendingIntentAndWaitWithPermission(action, timeout = TIMEOUT_SHORT)
+ }
+ }
+
+ @Test
+ fun sendActionPendingIntent_sourceStateChangedSafetyEvent_successNotification() {
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.criticalWithResolvingIssueWithSuccessMessage
+ )
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+ val action =
+ notificationWithChannel.statusBarNotification.notification.actions.firstOrNull()
+ checkNotNull(action) { "Notification action unexpectedly null" }
+ SafetySourceReceiver.setResponse(
+ Request.ResolveAction(SINGLE_SOURCE_ID),
+ Response.SetData(
+ safetySourceTestData.information,
+ overrideSafetyEvent =
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
)
)
+
+ sendActionPendingIntentAndWaitWithPermission(action)
+
+ TestNotificationListener.waitForSuccessNotification("Issue solved")
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE)
+ fun sendActionPendingIntent_actionIdDiffersFromIssueActionId_successNotification() {
+ val notification =
+ SafetySourceIssue.Notification.Builder("Custom title", "Custom text")
+ .addAction(
+ SafetySourceIssue.Action.Builder(
+ "notification_action_id",
+ "Solve now!",
+ safetySourceTestData.resolvingActionPendingIntent(
+ sourceIssueActionId = "notification_action_id"
+ )
+ )
+ .setWillResolve(true)
+ .setSuccessMessage("Solved via notification action :)")
+ .build()
+ )
+ .build()
+ val data =
+ safetySourceTestData
+ .defaultCriticalDataBuilder()
+ .clearIssues()
+ .addIssue(
+ safetySourceTestData
+ .defaultCriticalResolvingIssueBuilder()
+ .clearActions()
+ .addAction(
+ SafetySourceIssue.Action.Builder(
+ "issue_action_id",
+ "Default action",
+ safetySourceTestData.resolvingActionPendingIntent(
+ sourceIssueActionId = "issue_action_id"
+ )
+ )
+ .setWillResolve(true)
+ .setSuccessMessage("Solved via issue action :(")
+ .build()
+ )
+ .setCustomNotification(notification)
+ .setNotificationBehavior(
+ SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY
+ )
+ .build()
+ )
+ .build()
+
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, data)
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+ val action =
+ notificationWithChannel.statusBarNotification.notification.actions.firstOrNull()
+ checkNotNull(action) { "Notification action unexpectedly null" }
+ SafetySourceReceiver.setResponse(
+ Request.ResolveAction(SINGLE_SOURCE_ID),
+ Response.SetData(safetySourceTestData.information)
+ )
+
+ sendActionPendingIntentAndWaitWithPermission(action)
+
+ TestNotificationListener.waitForSuccessNotification("Solved via notification action :)")
}
@Test
@@ -941,12 +1066,10 @@ class SafetyCenterNotificationTest {
safetySourceTestData.recommendationWithDeviceIssue
)
val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
- val contentIntent = notificationWithChannel.statusBarNotification.notification.contentIntent
- executeBlockAndExit(
- launchActivity = { PendingIntentSender.send(contentIntent) },
- block = { waitSourceIssueDisplayed(safetySourceTestData.recommendationDeviceIssue) }
- )
+ sendContentPendingIntent(notificationWithChannel) {
+ waitSourceIssueDisplayed(safetySourceTestData.recommendationDeviceIssue)
+ }
}
@Test
@@ -962,34 +1085,69 @@ class SafetyCenterNotificationTest {
safetySourceTestData.criticalWithResolvingGeneralIssue
)
val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
- val contentIntent = notificationWithChannel.statusBarNotification.notification.contentIntent
- executeBlockAndExit(
- launchActivity = { PendingIntentSender.send(contentIntent) },
- block = {
- waitSourceIssueDisplayed(safetySourceTestData.criticalResolvingGeneralIssue)
- waitSourceIssueDisplayed(safetySourceTestData.recommendationGeneralIssue)
- }
+ sendContentPendingIntent(notificationWithChannel) {
+ waitSourceIssueDisplayed(safetySourceTestData.criticalResolvingGeneralIssue)
+ waitSourceIssueDisplayed(safetySourceTestData.recommendationDeviceIssue)
+ }
+ }
+
+ @Test
+ fun whenGreenIssue_notificationHasAutoCancel() {
+ safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, safetySourceTestData.informationWithIssue)
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+
+ assertThat(notificationWithChannel.statusBarNotification.hasAutoCancel()).isTrue()
+ }
+
+ @Test
+ fun whenNotGreenIssue_notificationDoesntHaveAutoCancel() {
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.recommendationWithDeviceIssue
)
+ val notificationWithChannel = TestNotificationListener.waitForSingleNotification()
+
+ assertThat(notificationWithChannel.statusBarNotification.hasAutoCancel()).isFalse()
}
- companion object {
- private val SafetyCenterData.inFlightActions: List<SafetyCenterIssue.Action>
+ private companion object {
+ val SafetyCenterData.inFlightActions: List<SafetyCenterIssue.Action>
get() = issues.flatMap { it.actions }.filter { it.isInFlight }
- private fun sendActionPendingIntentAndWaitWithPermission(action: Notification.Action) {
+ fun sendActionPendingIntentAndWaitWithPermission(
+ action: Notification.Action,
+ timeout: Duration = Coroutines.TIMEOUT_LONG
+ ) {
callWithShellPermissionIdentity(SEND_SAFETY_CENTER_UPDATE) {
PendingIntentSender.send(action.actionIntent)
// Sending the action's PendingIntent above is asynchronous and we need to wait for
// it to be received by the fake receiver below.
- SafetySourceReceiver.receiveResolveAction()
+ SafetySourceReceiver.receiveResolveAction(timeout)
}
}
- private fun setFlagsForImmediateNotifications(vararg sourceIds: String) {
+ fun setFlagsForImmediateNotifications(vararg sourceIds: String) {
SafetyCenterFlags.notificationsAllowedSources = sourceIds.toSet()
SafetyCenterFlags.immediateNotificationBehaviorIssues =
sourceIds.map { "$it/$ISSUE_TYPE_ID" }.toSet()
}
+
+ fun StatusBarNotification.hasAutoCancel(): Boolean {
+ val autoCancelMask = notification.flags and Notification.FLAG_AUTO_CANCEL
+ return autoCancelMask != 0
+ }
+
+ fun sendContentPendingIntent(
+ statusBarNotificationWithChannel: StatusBarNotificationWithChannel,
+ andExecuteBlock: () -> Unit = {}
+ ) {
+ val contentIntent =
+ statusBarNotificationWithChannel.statusBarNotification.notification.contentIntent
+ executeBlockAndExit(
+ launchActivity = { PendingIntentSender.send(contentIntent) },
+ block = andExecuteBlock
+ )
+ }
}
}
diff --git a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterShellCommandsTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterShellCommandsTest.kt
index b0860d751..7c5b41944 100644
--- a/tests/cts/safetycenter/src/android/safetycenter/cts/SafetyCenterShellCommandsTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/SafetyCenterShellCommandsTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,20 +14,23 @@
* limitations under the License.
*/
-package android.safetycenter.cts
+package android.safetycenter.functional
+import android.Manifest.permission.INTERACT_ACROSS_USERS
+import android.app.ActivityManager
import android.content.Context
import android.safetycenter.SafetyCenterManager
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compatibility.common.util.SystemUtil
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.isSafetyCenterEnabledWithPermission
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
+import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.deviceSupportsSafetyCenter
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
-/** CTS tests for Safety Center's shell commands. */
+/** Tests for Safety Center's shell commands. */
@RunWith(AndroidJUnit4::class)
class SafetyCenterShellCommandsTest {
private val context: Context = getApplicationContext()
@@ -54,6 +57,39 @@ class SafetyCenterShellCommandsTest {
assertThat(packageName).isEqualTo(context.packageManager.permissionControllerPackageName)
}
+ @Test
+ fun clearData_executesSuccessfully() {
+ executeShellCommand("cmd safety_center clear-data")
+ }
+
+ @Test
+ fun refresh_executesSuccessfully() {
+ val currentUser =
+ callWithShellPermissionIdentity(INTERACT_ACROSS_USERS) {
+ ActivityManager.getCurrentUser()
+ }
+ executeShellCommand("cmd safety_center refresh --reason OTHER --user $currentUser")
+ }
+
+ @Test
+ fun help_containsAllCommands() {
+ val help = executeShellCommand("cmd safety_center help")
+
+ assertThat(help).contains("help")
+ assertThat(help).contains("enabled")
+ assertThat(help).contains("supported")
+ assertThat(help).contains("package-name")
+ assertThat(help).contains("clear-data")
+ assertThat(help).contains("refresh")
+ }
+
+ @Test
+ fun dump_containsSafetyCenterService() {
+ val dump = executeShellCommand("dumpsys safety_center")
+
+ assertThat(dump).contains("SafetyCenterService")
+ }
+
private fun executeShellCommand(command: String): String =
- SystemUtil.runShellCommand(command).trim()
+ SystemUtil.runShellCommandOrThrow(command).trim()
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterQsActivityTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterQsActivityTest.kt
index 9c4d720d3..73d6a0737 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterQsActivityTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterQsActivityTest.kt
@@ -16,29 +16,23 @@
package android.safetycenter.functional.ui
-import android.Manifest.permission.MANAGE_SENSOR_PRIVACY
-import android.Manifest.permission.OBSERVE_SENSOR_PRIVACY
import android.content.Context
-import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.Sensors.CAMERA
import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
-import android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE
-import android.platform.test.rule.ScreenRecordRule
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.By
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
+import com.android.safetycenter.testing.EnableSensorRule
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterQsActivity
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestHelper
-import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import com.android.safetycenter.testing.SafetyCenterTestRule
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
-import org.junit.After
-import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -48,66 +42,22 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterQsActivityTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
- @get:Rule val screenRecordRule = ScreenRecordRule()
-
private val context: Context = getApplicationContext()
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
- private val sensorPrivacyManager = context.getSystemService(SensorPrivacyManager::class.java)!!
- private var shouldRunTests =
- context.deviceSupportsSafetyCenter() &&
- deviceSupportsSensorToggle(CAMERA) &&
- deviceSupportsSensorToggle(MICROPHONE)
- private var oldCameraState: Boolean = false
- private var oldMicrophoneState: Boolean = false
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val enableCameraRule = EnableSensorRule(context, CAMERA)
+ @get:Rule(order = 3) val enableMicrophoneRule = EnableSensorRule(context, MICROPHONE)
+ @get:Rule(order = 4) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 5) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 6) val freezeRotationRule = FreezeRotationRule()
@Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
+ fun setTestConfigBeforeTest() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
}
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
-
- @Before
- fun enablePrivacyControlsBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- oldCameraState = isSensorEnabled(CAMERA)
- setSensorState(CAMERA, true)
-
- oldMicrophoneState = isSensorEnabled(MICROPHONE)
- setSensorState(MICROPHONE, true)
- }
-
- @After
- fun restorePrivacyControlsAfterTest() {
- if (!shouldRunTests) {
- return
- }
- setSensorState(CAMERA, oldCameraState)
- setSensorState(MICROPHONE, oldMicrophoneState)
- }
-
@Test
fun launchActivity_fromQuickSettings_hasContentDescriptions() {
context.launchSafetyCenterQsActivity {
@@ -122,7 +72,6 @@ class SafetyCenterQsActivityTest {
}
@Test
- @ScreenRecordRule.ScreenRecord
fun launchActivity_togglePrivacyControls_hasUpdatedDescriptions() {
context.launchSafetyCenterQsActivity {
// Toggle privacy controls
@@ -134,25 +83,4 @@ class SafetyCenterQsActivityTest {
waitDisplayed(By.desc("Switch. Mic access. Blocked"))
}
}
-
- private fun deviceSupportsSensorToggle(sensor: Int): Boolean {
- return sensorPrivacyManager.supportsSensorToggle(sensor) &&
- sensorPrivacyManager.supportsSensorToggle(TOGGLE_TYPE_SOFTWARE, sensor)
- }
-
- private fun isSensorEnabled(sensor: Int): Boolean {
- val isSensorDisabled =
- callWithShellPermissionIdentity(OBSERVE_SENSOR_PRIVACY) {
- sensorPrivacyManager.isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor)
- }
- return !isSensorDisabled
- }
-
- private fun setSensorState(sensor: Int, enabled: Boolean) {
- val disableSensor = !enabled
- // The sensor is enabled iff the privacy control is disabled.
- callWithShellPermissionIdentity(MANAGE_SENSOR_PRIVACY, OBSERVE_SENSOR_PRIVACY) {
- sensorPrivacyManager.setSensorPrivacy(sensor, disableSensor)
- }
- }
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
index f4ed328ae..5655b935b 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
+++ b/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterStatusCardTest.kt
@@ -22,26 +22,24 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.By
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.RESCAN_BUTTON_LABEL
import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitButtonDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitButtonNotDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitNotDisplayed
-import org.junit.After
-import org.junit.Assume.assumeTrue
-import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -50,42 +48,17 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SafetyCenterStatusCardTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = getApplicationContext()
-
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestData = SafetyCenterTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
- // JUnit's Assume is not supported in @BeforeClass by the tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
- }
-
- @After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Test
fun withUnknownStatus_displaysScanningOnLoad() {
@@ -93,8 +66,8 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("scanning_title"),
- safetyCenterResourcesContext.getStringByName("loading_summary")
+ safetyCenterResourcesApk.getStringByName("scanning_title"),
+ safetyCenterResourcesApk.getStringByName("loading_summary")
)
}
}
@@ -109,8 +82,8 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName("loading_summary")
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("loading_summary")
)
}
}
@@ -122,12 +95,8 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_title"
- ),
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_summary"
- )
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_review_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_review_summary")
)
waitButtonDisplayed(RESCAN_BUTTON_LABEL)
}
@@ -143,8 +112,8 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_summary")
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_summary")
)
waitButtonDisplayed(RESCAN_BUTTON_LABEL)
}
@@ -174,7 +143,7 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
safetyCenterTestData.getAlertString(1)
)
waitButtonNotDisplayed(RESCAN_BUTTON_LABEL)
@@ -191,7 +160,7 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName(
+ safetyCenterResourcesApk.getStringByName(
"overall_severity_level_safety_recommendation_title"
),
safetyCenterTestData.getAlertString(1)
@@ -210,7 +179,7 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName(
+ safetyCenterResourcesApk.getStringByName(
"overall_severity_level_critical_safety_warning_title"
),
safetyCenterTestData.getAlertString(1)
@@ -229,15 +198,15 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_summary")
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_summary")
)
waitButtonDisplayed(RESCAN_BUTTON_LABEL) { it.click() }
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("scanning_title"),
- safetyCenterResourcesContext.getStringByName("loading_summary")
+ safetyCenterResourcesApk.getStringByName("scanning_title"),
+ safetyCenterResourcesApk.getStringByName("loading_summary")
)
}
}
@@ -256,14 +225,14 @@ class SafetyCenterStatusCardTest {
context.launchSafetyCenterActivity(withReceiverPermission = true) {
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_summary")
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_summary")
)
waitButtonDisplayed(RESCAN_BUTTON_LABEL) { it.click() }
waitAllTextDisplayed(
- safetyCenterResourcesContext.getStringByName(
+ safetyCenterResourcesApk.getStringByName(
"overall_severity_level_safety_recommendation_title"
),
safetyCenterTestData.getAlertString(1)
diff --git a/tests/functional/safetycenter/subpages/Android.bp b/tests/functional/safetycenter/subpages/Android.bp
new file mode 100644
index 000000000..4279ca26f
--- /dev/null
+++ b/tests/functional/safetycenter/subpages/Android.bp
@@ -0,0 +1,43 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "SafetyCenterSubpagesTestCases",
+ defaults: ["mts-target-sdk-version-current"],
+ sdk_version: "test_current",
+ min_sdk_version: "30",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "androidx.test.monitor",
+ "compatibility-device-preconditions",
+ "kotlin-test",
+ "platform-test-rules",
+ "safety-center-test-util-lib",
+ ],
+ test_suites: [
+ "general-tests",
+ "mts-permission",
+ ],
+}
diff --git a/tests/functional/safetycenter/subpages/AndroidManifest.xml b/tests/functional/safetycenter/subpages/AndroidManifest.xml
new file mode 100644
index 000000000..ea59a99c6
--- /dev/null
+++ b/tests/functional/safetycenter/subpages/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.safetycenter.functional.subpages">
+ <application>
+
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Functional tests for SafetyCenter Subpages"
+ android:targetPackage="android.safetycenter.functional.subpages"/>
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+</manifest>
diff --git a/tests/functional/safetycenter/subpages/AndroidTest.xml b/tests/functional/safetycenter/subpages/AndroidTest.xml
new file mode 100644
index 000000000..c3245e9d7
--- /dev/null
+++ b/tests/functional/safetycenter/subpages/AndroidTest.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<configuration description="Config for SafetyCenter subpages testcases">
+
+ <object
+ class="com.android.tradefed.testtype.suite.module.Sdk34ModuleController"
+ type="module_controller"/>
+
+ <option name="config-descriptor:metadata" key="component" value="framework"/>
+ <option name="config-descriptor:metadata" key="parameter"
+ value="not_instant_app"/>
+ <option name="config-descriptor:metadata" key="parameter"
+ value="not_multi_abi"/>
+ <option name="config-descriptor:metadata" key="parameter"
+ value="secondary_user"/>
+ <option name="config-descriptor:metadata" key="mainline-param" value="com.google.android.permission.apex" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
+
+ <option name="test-suite-tag" value="functional"/>
+
+ <target_preparer
+ class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="SafetyCenterSubpagesTestCases.apk"/>
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <!-- Ensure all broadcasts are dispatched prior to running our tests, to make sure they
+ aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
+ causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
+ <option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
+ <!-- Disable syncing to prevent overwriting flags during testing. -->
+ <option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
+ <option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
+ </target_preparer>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/user/0/android.safetycenter.functional.subpages/files" />
+ <option name="collect-on-run-ended-only" value="true" />
+ </metrics_collector>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.safetycenter.functional.subpages"/>
+ <option name="exclude-annotation" value="org.junit.Ignore"/>
+ <option name="runtime-hint" value="10m"/>
+ </test>
+</configuration>
diff --git a/tests/functional/safetycenter/subpages/TEST_MAPPING b/tests/functional/safetycenter/subpages/TEST_MAPPING
new file mode 100644
index 000000000..e6802586e
--- /dev/null
+++ b/tests/functional/safetycenter/subpages/TEST_MAPPING
@@ -0,0 +1,17 @@
+{
+ "presubmit": [
+ {
+ "name": "SafetyCenterSubpagesTestCases"
+ }
+ ],
+ "mainline-presubmit": [
+ {
+ "name": "SafetyCenterSubpagesTestCases[com.google.android.permission.apex]",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt
index 0c90029e0..7ad83b949 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt
+++ b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/PrivacySubpageTest.kt
@@ -17,13 +17,15 @@
package android.safetycenter.functional.ui
import android.content.Context
-import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
+import android.content.pm.PackageManager
+import android.hardware.SensorPrivacyManager
+import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.os.Bundle
import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID
import android.safetycenter.config.SafetySource
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
import androidx.test.uiautomator.By
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
@@ -31,23 +33,24 @@ import com.android.compatibility.common.util.UiAutomatorUtils2
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAndExit
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.PRIVACY_SOURCE_ID_1
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_1
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.MORE_ISSUES_LABEL
import com.android.safetycenter.testing.UiTestHelper.clickMoreIssuesCard
import com.android.safetycenter.testing.UiTestHelper.resetRotation
import com.android.safetycenter.testing.UiTestHelper.waitAllTextDisplayed
+import com.android.safetycenter.testing.UiTestHelper.waitAllTextNotDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitButtonDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueNotDisplayed
import org.junit.After
-import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -55,42 +58,27 @@ import org.junit.runner.RunWith
/** Functional tests for the Privacy subpage in Safety Center. */
@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
class PrivacySubpageTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
private val context: Context = getApplicationContext()
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ private val sensorPrivacyManager: SensorPrivacyManager =
+ context.getSystemService(SensorPrivacyManager::class.java)!!
- // JUnit's Assume is not supported in @BeforeClass by the tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
-
- @Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Before
fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
SafetyCenterFlags.showSubpages = true
}
@After
fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
UiAutomatorUtils2.getUiDevice().resetRotation()
}
@@ -166,13 +154,20 @@ class PrivacySubpageTest {
extras.putString(EXTRA_SAFETY_SOURCES_GROUP_ID, config.safetySourcesGroups.first().id)
context.launchSafetyCenterActivity(extras) {
- waitAllTextDisplayed(
- "Camera access",
- "Microphone access",
- "Show clipboard access",
- "Show passwords",
- "Location access"
+ waitAllText(
+ displayed = sensorPrivacyManager.supportsSensorToggle(CAMERA),
+ text = "Camera access"
+ )
+ waitAllText(
+ displayed = sensorPrivacyManager.supportsSensorToggle(MICROPHONE),
+ text = "Microphone access"
+ )
+ waitAllTextDisplayed("Show clipboard access")
+ waitAllText(
+ displayed = getPermissionControllerBool("config_display_show_password_toggle"),
+ text = "Show passwords"
)
+ waitAllTextDisplayed("Location access")
}
}
@@ -216,6 +211,34 @@ class PrivacySubpageTest {
}
}
+ private fun waitAllText(displayed: Boolean, text: String) {
+ if (displayed) {
+ waitAllTextDisplayed(text)
+ } else {
+ waitAllTextNotDisplayed(text)
+ }
+ }
+
+ private fun getPermissionControllerBool(resourceName: String): Boolean {
+ val permissionControllerContext = getPermissionControllerContext()
+ val resourceId =
+ permissionControllerContext.resources.getIdentifier(
+ resourceName,
+ "bool",
+ "com.android.permissioncontroller"
+ )
+ return permissionControllerContext.resources.getBoolean(resourceId)
+ }
+
+ private fun getPermissionControllerContext(): Context {
+ val permissionControllerPkg = context.packageManager.permissionControllerPackageName
+ try {
+ return context.createPackageContext(permissionControllerPkg, 0)
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw RuntimeException(e)
+ }
+ }
+
companion object {
private const val EXTRA_SETTINGS_FRAGMENT_ARGS_KEY = ":settings:fragment_args_key"
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
index eeb512037..236beb34e 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
+++ b/tests/functional/safetycenter/subpages/src/android/safetycenter/functional/ui/SafetyCenterSubpagesTest.kt
@@ -17,7 +17,6 @@
package android.safetycenter.functional.ui
import android.content.Context
-import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.Bundle
import android.safetycenter.SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID
import android.safetycenter.SafetySourceData
@@ -26,21 +25,16 @@ import android.safetycenter.config.SafetySource
import android.safetycenter.config.SafetySourcesGroup
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import com.android.compatibility.common.util.DisableAnimationRule
import com.android.compatibility.common.util.FreezeRotationRule
-import com.android.compatibility.common.util.RetryRule
import com.android.compatibility.common.util.UiAutomatorUtils2
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.launchSafetyCenterActivity
import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAndExit
-import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAndExitAllowingRetries
import com.android.safetycenter.testing.SafetyCenterFlags
-import com.android.safetycenter.testing.SafetyCenterFlags.deviceSupportsSafetyCenter
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.MULTIPLE_SOURCES_GROUP_ID_1
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
@@ -51,10 +45,12 @@ import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_5
import com.android.safetycenter.testing.SafetyCenterTestData
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
import com.android.safetycenter.testing.SafetySourceReceiver
import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SupportsSafetyCenterRule
import com.android.safetycenter.testing.UiTestHelper.MORE_ISSUES_LABEL
import com.android.safetycenter.testing.UiTestHelper.clickConfirmDismissal
import com.android.safetycenter.testing.UiTestHelper.clickDismissIssueCard
@@ -75,64 +71,34 @@ import com.android.safetycenter.testing.UiTestHelper.waitPageTitleDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitPageTitleNotDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueDisplayed
import com.android.safetycenter.testing.UiTestHelper.waitSourceIssueNotDisplayed
-import java.util.concurrent.TimeUnit
import org.junit.After
-import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
-import org.junit.rules.Timeout
import org.junit.runner.RunWith
/** Functional tests for generic subpages in Safety Center. */
@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = UPSIDE_DOWN_CAKE, codeName = "UpsideDownCake")
class SafetyCenterSubpagesTest {
- @get:Rule val disableAnimationRule = DisableAnimationRule()
-
- @get:Rule val freezeRotationRule = FreezeRotationRule()
-
- // It is necessery to couple RetryRule and Timeout to ensure that all the retries together are
- // restricted with the test timeout
- @get:Rule val retryRule = RetryRule(/* retries= */ 3)
- @get:Rule
- val timeoutRule =
- Timeout(
- InstrumentationRegistry.getArguments().getString("timeout_msec", "60000").toLong(),
- TimeUnit.MILLISECONDS
- )
-
private val context: Context = getApplicationContext()
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
- // JUnit's Assume is not supported in @BeforeClass by the tests runner, so this is used to
- // manually skip the setup and teardown methods.
- private val shouldRunTests = context.deviceSupportsSafetyCenter()
+ @get:Rule(order = 1) val supportsSafetyCenterRule = SupportsSafetyCenterRule(context)
+ @get:Rule(order = 2) val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+ @get:Rule(order = 3) val disableAnimationRule = DisableAnimationRule()
+ @get:Rule(order = 4) val freezeRotationRule = FreezeRotationRule()
@Before
- fun assumeDeviceSupportsSafetyCenterToRunTests() {
- assumeTrue(shouldRunTests)
- }
-
- @Before
- fun enableSafetyCenterBeforeTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.setup()
+ fun enableSubpagesBeforeTest() {
SafetyCenterFlags.showSubpages = true
}
@After
- fun clearDataAfterTest() {
- if (!shouldRunTests) {
- return
- }
- safetyCenterTestHelper.reset()
+ fun resetRotationAfterTest() {
UiAutomatorUtils2.getUiDevice().resetRotation()
}
@@ -527,7 +493,7 @@ class SafetyCenterSubpagesTest {
)
context.launchSafetyCenterActivity(withReceiverPermission = true) {
- openPageAndExitAllowingRetries(context.getString(sourcesGroup.titleResId)) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
waitSourceIssueDisplayed(issue)
waitButtonDisplayed(action.label) { it.click() }
@@ -547,7 +513,7 @@ class SafetyCenterSubpagesTest {
val issue = sourceData.issues[0]
context.launchSafetyCenterActivity {
- openPageAndExitAllowingRetries(context.getString(sourcesGroup.titleResId)) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
waitSourceIssueDisplayed(issue)
clickDismissIssueCard()
@@ -568,7 +534,7 @@ class SafetyCenterSubpagesTest {
val issue = sourceData.issues[0]
context.launchSafetyCenterActivity {
- openPageAndExitAllowingRetries(context.getString(sourcesGroup.titleResId)) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
waitSourceIssueDisplayed(issue)
clickDismissIssueCard()
waitAllTextDisplayed("Dismiss this alert?")
@@ -611,7 +577,7 @@ class SafetyCenterSubpagesTest {
val issue = sourceData.issues[0]
context.launchSafetyCenterActivity {
- openPageAndExitAllowingRetries(context.getString(sourcesGroup.titleResId)) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
waitSourceIssueDisplayed(issue)
clickDismissIssueCard()
waitAllTextDisplayed("Dismiss this alert?")
@@ -635,7 +601,7 @@ class SafetyCenterSubpagesTest {
val issue = sourceData.issues[0]
context.launchSafetyCenterActivity {
- openPageAndExitAllowingRetries(context.getString(sourcesGroup.titleResId)) {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
waitSourceIssueDisplayed(issue)
clickDismissIssueCard()
waitAllTextDisplayed("Dismiss this alert?")
@@ -822,6 +788,24 @@ class SafetyCenterSubpagesTest {
}
@Test
+ fun dismissedIssuesCard_doesntShowGreenCards() {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ val (sourcesGroup, issue) =
+ prepareSingleSourceGroupWithIssue(
+ safetySourceTestData.informationWithIssueWithAttributionTitle
+ )
+ val safetyCenterIssueId = SafetyCenterTestData.issueId(SINGLE_SOURCE_ID, issue.id)
+ safetyCenterTestHelper.dismissSafetyCenterIssue(safetyCenterIssueId)
+
+ context.launchSafetyCenterActivity {
+ openPageAndExit(context.getString(sourcesGroup.titleResId)) {
+ waitAllTextNotDisplayed("Dismissed alerts")
+ waitSourceIssueNotDisplayed(issue)
+ }
+ }
+ }
+
+ @Test
fun moreIssuesCard_expandWithDismissedIssues_showsAdditionalCards() {
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesInSingleGroupConfig)
@@ -968,9 +952,7 @@ class SafetyCenterSubpagesTest {
waitAllTextDisplayed(
context.getString(source.titleResId),
context.getString(source.summaryResId),
- safetyCenterResourcesContext.getStringByName(
- "test_single_source_group_id_footer"
- )
+ safetyCenterResourcesApk.getStringByName("test_single_source_group_id_footer")
)
}
}
diff --git a/tests/hostside/safetycenter/Android.bp b/tests/hostside/safetycenter/Android.bp
index 499e44f62..c66cae23a 100644
--- a/tests/hostside/safetycenter/Android.bp
+++ b/tests/hostside/safetycenter/Android.bp
@@ -27,6 +27,7 @@ java_test_host {
libs: [
"tradefed",
"junit",
+ "compatibility-host-util",
],
static_libs: [
"cts-statsd-atom-host-test-utils",
diff --git a/tests/hostside/safetycenter/AndroidTest.xml b/tests/hostside/safetycenter/AndroidTest.xml
index 09ddf9d84..a28b70c3c 100644
--- a/tests/hostside/safetycenter/AndroidTest.xml
+++ b/tests/hostside/safetycenter/AndroidTest.xml
@@ -28,9 +28,12 @@
aren't polluted by `BOOT_COMPLETED` or similar broadcasts still being delivered, which
causes our `ActivityManager#waitForBroadcastIdle()` calls to timeout. -->
<option name="run-command" value="am wait-for-broadcast-idle" />
+ <option name="run-command" value="am wait-for-broadcast-barrier" />
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
+ <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.StayAwakePreparer" />
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
index c72166c65..784701b8a 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterInteractionLoggingHelperTests.kt
@@ -26,8 +26,9 @@ import com.android.safetycenter.testing.SafetyCenterActivityLauncher.openPageAnd
import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestHelper
-import org.junit.After
+import com.android.safetycenter.testing.SafetyCenterTestRule
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -47,17 +48,13 @@ class SafetyCenterInteractionLoggingHelperTests {
private val safetyCenterTestHelper = SafetyCenterTestHelper(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ @get:Rule val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+
@Before
fun setUp() {
- safetyCenterTestHelper.setup()
SafetyCenterFlags.showSubpages = true
}
- @After
- fun tearDown() {
- safetyCenterTestHelper.reset()
- }
-
@Test
fun openSafetyCenter() {
context.launchSafetyCenterActivity {}
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
index f4677cfed..458516379 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetyCenterNotificationLoggingHelperTests.kt
@@ -25,9 +25,10 @@ import com.android.safetycenter.testing.SafetyCenterFlags
import com.android.safetycenter.testing.SafetyCenterTestConfigs
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceTestData
-import org.junit.After
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,20 +49,16 @@ class SafetyCenterNotificationLoggingHelperTests {
private val safetySourceTestData = SafetySourceTestData(context)
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
+ @get:Rule val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+
@Before
fun setUp() {
- safetyCenterTestHelper.setup()
SafetyCenterFlags.notificationsEnabled = true
SafetyCenterFlags.notificationsAllowedSources = setOf(SINGLE_SOURCE_ID)
SafetyCenterFlags.allowStatsdLogging = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
}
- @After
- fun tearDown() {
- safetyCenterTestHelper.reset()
- }
-
@Test
fun sendNotification() {
safetyCenterTestHelper.setData(SINGLE_SOURCE_ID, newTestDataWithNotifiableIssue())
diff --git a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
index b7bd60d10..4d945aad7 100644
--- a/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
+++ b/tests/hostside/safetycenter/helper-app/src/android/safetycenter/hostside/device/SafetySourceStateCollectedLoggingHelperTests.kt
@@ -23,16 +23,27 @@ import android.safetycenter.SafetySourceErrorDetails
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compatibility.common.util.SystemUtil
-import com.android.safetycenter.testing.*
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.reportSafetySourceErrorWithPermission
+import com.android.safetycenter.testing.SafetyCenterFlags
+import com.android.safetycenter.testing.SafetyCenterTestConfigs
+import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_ID
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_1
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_2
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SOURCE_ID_3
+import com.android.safetycenter.testing.SafetyCenterTestData
+import com.android.safetycenter.testing.SafetyCenterTestHelper
+import com.android.safetycenter.testing.SafetyCenterTestRule
import com.android.safetycenter.testing.SafetySourceIntentHandler.Request
import com.android.safetycenter.testing.SafetySourceIntentHandler.Response
+import com.android.safetycenter.testing.SafetySourceReceiver
+import com.android.safetycenter.testing.SafetySourceReceiver.Companion.executeSafetyCenterIssueActionWithPermissionAndWait
import com.android.safetycenter.testing.SafetySourceReceiver.Companion.refreshSafetySourcesWithReceiverPermissionAndWait
-import org.junit.After
+import com.android.safetycenter.testing.SafetySourceTestData
+import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ACTION_ID
+import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,18 +55,14 @@ class SafetySourceStateCollectedLoggingHelperTests {
private val safetyCenterTestConfigs = SafetyCenterTestConfigs(context)
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
+ @get:Rule val safetyCenterTestRule = SafetyCenterTestRule(safetyCenterTestHelper)
+
@Before
fun setUp() {
- safetyCenterTestHelper.setup()
SafetyCenterFlags.allowStatsdLogging = true
safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.multipleSourcesConfig)
}
- @After
- fun tearDown() {
- safetyCenterTestHelper.reset()
- }
-
@Test
fun triggerStatsPull() {
val label = 1 // Arbitrary label in [0, 16)
@@ -124,13 +131,11 @@ class SafetySourceStateCollectedLoggingHelperTests {
@Test
fun refreshAllSources_reasonPageOpen_oneSuccessOneErrorOneTimeout() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(Coroutines.TIMEOUT_SHORT)
simulateRefresh(Response.SetData(safetySourceTestData.information), Response.Error, null)
}
@Test
fun refreshAllSources_reasonButtonClick_oneSuccessOneErrorOneTimeout() {
- SafetyCenterFlags.setAllRefreshTimeoutsTo(Coroutines.TIMEOUT_SHORT)
simulateRefresh(
Response.SetData(safetySourceTestData.information),
Response.Error,
@@ -139,6 +144,16 @@ class SafetySourceStateCollectedLoggingHelperTests {
)
}
+ @Test
+ fun resolvingAction_success() {
+ simulateResolvingActionWith(Response.SetData(safetySourceTestData.information))
+ }
+
+ @Test
+ fun resolvingAction_error() {
+ simulateResolvingActionWith(Response.Error)
+ }
+
private fun simulateRefresh(
source1Response: Response?,
source2Response: Response?,
@@ -154,8 +169,35 @@ class SafetySourceStateCollectedLoggingHelperTests {
if (source3Response != null) {
SafetySourceReceiver.setResponse(Request.Refresh(SOURCE_ID_3), source3Response)
}
+
+ val atLeastOneTimeout =
+ source1Response == null || source2Response == null || source3Response == null
+ if (atLeastOneTimeout) {
+ SafetyCenterFlags.setAllRefreshTimeoutsTo(TIMEOUT_SHORT)
+ }
+
+ // Refresh sources and wait until the refresh has fully completed / timed out to ensure that
+ // things are logged.
+ val listener = safetyCenterTestHelper.addListener()
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(refreshReason)
- // Give time for responses to all sources
- Thread.sleep(Coroutines.TIMEOUT_SHORT.toMillis())
+ listener.waitForSafetyCenterRefresh()
+ }
+
+ private fun simulateResolvingActionWith(response: Response) {
+ safetyCenterTestHelper.setConfig(safetyCenterTestConfigs.singleSourceConfig)
+ safetyCenterTestHelper.setData(
+ SINGLE_SOURCE_ID,
+ safetySourceTestData.criticalWithResolvingGeneralIssue
+ )
+ SafetySourceReceiver.setResponse(Request.ResolveAction(SINGLE_SOURCE_ID), response)
+
+ safetyCenterManager.executeSafetyCenterIssueActionWithPermissionAndWait(
+ SafetyCenterTestData.issueId(SINGLE_SOURCE_ID, CRITICAL_ISSUE_ID),
+ SafetyCenterTestData.issueActionId(
+ SINGLE_SOURCE_ID,
+ CRITICAL_ISSUE_ID,
+ CRITICAL_ISSUE_ACTION_ID
+ )
+ )
}
}
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
index 5ef8ed84a..5fe9e0a2a 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterInteractionLoggingHostTest.kt
@@ -20,6 +20,7 @@ import android.cts.statsdatom.lib.ConfigUtils
import android.cts.statsdatom.lib.ReportUtils
import android.safetycenter.hostside.rules.HelperAppRule
import android.safetycenter.hostside.rules.RequireSafetyCenterRule
+import com.android.compatibility.common.util.ApiLevelUtil
import com.android.os.AtomsProto.Atom
import com.android.os.AtomsProto.SafetyCenterInteractionReported
import com.android.os.AtomsProto.SafetyCenterInteractionReported.Action
@@ -28,23 +29,19 @@ import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
import com.google.common.truth.Truth.assertThat
import org.junit.After
+import org.junit.Assume.assumeTrue
import org.junit.Before
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
-import org.junit.rules.RuleChain
import org.junit.runner.RunWith
/** Host-side tests for Safety Center statsd logging. */
@RunWith(DeviceJUnit4ClassRunner::class)
class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
- private val safetyCenterRule = RequireSafetyCenterRule(this)
- private val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
-
- @Rule
- @JvmField
- val rules: RuleChain = RuleChain.outerRule(safetyCenterRule).around(helperAppRule)
+ @get:Rule(order = 1) val safetyCenterRule = RequireSafetyCenterRule(this)
+ @get:Rule(order = 2)
+ val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
@Before
fun setUp() {
@@ -75,6 +72,8 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
@Test
fun sendNotification_recordsNotificationPostedEvent() {
+ assumeAtLeastUpsideDownCake("Safety Center notification APIs require Android U+")
+
helperAppRule.runTest(
testClassName = ".SafetyCenterNotificationLoggingHelperTests",
testMethodName = "sendNotification"
@@ -89,6 +88,8 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
@Test
fun openSubpageFromIntentExtra_recordsEventWithUnknownNavigationSource() {
+ assumeAtLeastUpsideDownCake("Safety Center subpages require Android U+")
+
helperAppRule.runTest(TEST_CLASS_NAME, testMethodName = "openSubpageFromIntentExtra")
val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
@@ -103,25 +104,24 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
}
@Test
- @Ignore
- // TODO(b/278202773): Fix/de-flake this test
fun openSubpageFromHomepage_recordsEventWithSafetyCenterNavigationSource() {
+ assumeAtLeastUpsideDownCake("Safety Center subpages require Android U+")
+
helperAppRule.runTest(TEST_CLASS_NAME, testMethodName = "openSubpageFromHomepage")
val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
+ val subpageViewedEvent = safetyCenterViewedAtoms.find { it.viewType == ViewType.SUBPAGE }
- assertThat(safetyCenterViewedAtoms.map { it.viewType })
- .containsExactly(ViewType.FULL, ViewType.SUBPAGE, ViewType.FULL)
- .inOrder()
- assertThat(safetyCenterViewedAtoms[1].navigationSource)
+ assertThat(subpageViewedEvent).isNotNull()
+ assertThat(subpageViewedEvent!!.navigationSource)
.isEqualTo(SafetyCenterInteractionReported.NavigationSource.SAFETY_CENTER)
assertThat(safetyCenterViewedAtoms.map { it.sessionId }.distinct()).hasSize(1)
}
@Test
- @Ignore
- // TODO(b/278202773): Fix/de-flake this test
fun openSubpageFromSettingsSearch_recordsEventWithSettingsNavigationSource() {
+ assumeAtLeastUpsideDownCake("Safety Center subpages require Android U+")
+
helperAppRule.runTest(TEST_CLASS_NAME, testMethodName = "openSubpageFromSettingsSearch")
val safetyCenterViewedAtoms = getInteractionReportedAtoms(Action.SAFETY_CENTER_VIEWED)
@@ -142,6 +142,10 @@ class SafetyCenterInteractionLoggingHostTest : BaseHostJUnit4Test() {
.mapNotNull { it.atom.safetyCenterInteractionReported }
.filter { it.action == action }
+ private fun assumeAtLeastUpsideDownCake(message: String) {
+ assumeTrue(message, ApiLevelUtil.isAtLeast(device, 34))
+ }
+
private companion object {
const val TEST_CLASS_NAME = ".SafetyCenterInteractionLoggingHelperTests"
}
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterSystemEventReportedLoggingHostTest.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterSystemEventReportedLoggingHostTest.kt
index 65e47fa91..2589c7a47 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterSystemEventReportedLoggingHostTest.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetyCenterSystemEventReportedLoggingHostTest.kt
@@ -31,18 +31,14 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
-import org.junit.rules.RuleChain
import org.junit.runner.RunWith
@RunWith(DeviceJUnit4ClassRunner::class)
class SafetyCenterSystemEventReportedLoggingHostTest : BaseHostJUnit4Test() {
- private val safetyCenterRule = RequireSafetyCenterRule(this)
- private val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
-
- @Rule
- @JvmField
- val rules: RuleChain = RuleChain.outerRule(safetyCenterRule).around(helperAppRule)
+ @get:Rule(order = 1) val safetyCenterRule = RequireSafetyCenterRule(this)
+ @get:Rule(order = 2)
+ val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
@Before
fun setUp() {
@@ -143,6 +139,7 @@ class SafetyCenterSystemEventReportedLoggingHostTest : BaseHostJUnit4Test() {
.that(systemEventAtoms.count { it.refreshReason == REFRESH_REASON_BUTTON_CLICK })
}
+ @Test
fun refreshAllSources_firstTime_allSourcesSuccessful_dataChangedTrueForAll() {
helperAppRule.runTest(
".SafetySourceStateCollectedLoggingHelperTests",
@@ -183,18 +180,50 @@ class SafetyCenterSystemEventReportedLoggingHostTest : BaseHostJUnit4Test() {
@Test
fun refreshAllSources_secondTime_someSourcesChanged_dataChangedCorrect() {
helperAppRule.runTest(
- ".SafetySourceStateCollectedLoggingHelperTests",
- "refreshAllSources_twiceDifferentData_onlySource1Unchanged"
+ ".SafetySourceStateCollectedLoggingHelperTests",
+ "refreshAllSources_twiceDifferentData_onlySource1Unchanged"
)
val systemEventAtoms =
- ReportUtils.getEventMetricDataList(device).mapNotNull {
- it.atom.safetyCenterSystemEventReported
- }
+ ReportUtils.getEventMetricDataList(device).mapNotNull {
+ it.atom.safetyCenterSystemEventReported
+ }
assertWithMessage("the number of atoms with dataChanged=false")
- .that(systemEventAtoms.count { !it.dataChanged })
- .isEqualTo(1) // Only source 1
+ .that(systemEventAtoms.count { !it.dataChanged })
+ .isEqualTo(1) // Only source 1
+ }
+
+ @Test
+ fun resolveAction_success_resolvingActionSuccessEvent() {
+ helperAppRule.runTest(
+ ".SafetySourceStateCollectedLoggingHelperTests",
+ "resolvingAction_success"
+ )
+
+ val resolvingActionEvent =
+ ReportUtils.getEventMetricDataList(device)
+ .mapNotNull { it.atom.safetyCenterSystemEventReported }
+ .single { it.eventType == EventType.INLINE_ACTION }
+
+ assertThat(resolvingActionEvent.result).isEqualTo(Result.SUCCESS)
+ assertThat(resolvingActionEvent.encodedIssueTypeId).isNotEqualTo(0)
+ }
+
+ @Test
+ fun resolveAction_error_resolvingActionErrorEvent() {
+ helperAppRule.runTest(
+ ".SafetySourceStateCollectedLoggingHelperTests",
+ "resolvingAction_error"
+ )
+
+ val resolvingActionEvent =
+ ReportUtils.getEventMetricDataList(device)
+ .mapNotNull { it.atom.safetyCenterSystemEventReported }
+ .single { it.eventType == EventType.INLINE_ACTION }
+
+ assertThat(resolvingActionEvent.result).isEqualTo(Result.ERROR)
+ assertThat(resolvingActionEvent.encodedIssueTypeId).isNotEqualTo(0)
}
companion object {
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetySourceStateCollectedLoggingHostTest.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetySourceStateCollectedLoggingHostTest.kt
index 22a380e12..a86041b5b 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetySourceStateCollectedLoggingHostTest.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/SafetySourceStateCollectedLoggingHostTest.kt
@@ -29,19 +29,15 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
-import org.junit.rules.RuleChain
import org.junit.runner.RunWith
/** Host-side tests for Safety Center statsd logging. */
@RunWith(DeviceJUnit4ClassRunner::class)
class SafetySourceStateCollectedLoggingHostTest : BaseHostJUnit4Test() {
- private val safetyCenterRule = RequireSafetyCenterRule(this)
- private val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
-
- @Rule
- @JvmField
- val rules: RuleChain = RuleChain.outerRule(safetyCenterRule).around(helperAppRule)
+ @get:Rule(order = 1) val safetyCenterRule = RequireSafetyCenterRule(this)
+ @get:Rule(order = 2)
+ val helperAppRule = HelperAppRule(this, HelperApp.APK_NAME, HelperApp.PACKAGE_NAME)
@Before
fun setUp() {
@@ -66,8 +62,10 @@ class SafetySourceStateCollectedLoggingHostTest : BaseHostJUnit4Test() {
val sourceStateAtoms = getSafetySourceStateCollectedAtoms()
+ // This assertion purposefully uses containsAtLeast and not containsExact because on test
+ // devices with multiple primary users there will be multiple atoms per source.
assertThat(sourceStateAtoms.map { it.encodedSafetySourceId })
- .containsExactly(
+ .containsAtLeast(
SOURCE_1_ENCODED_SOURCE_ID,
SOURCE_2_ENCODED_SOURCE_ID,
SOURCE_3_ENCODED_SOURCE_ID
diff --git a/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt b/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
index 809fe5f0f..edf76e888 100644
--- a/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
+++ b/tests/hostside/safetycenter/src/android/safetycenter/hostside/rules/RequireSafetyCenterRule.kt
@@ -28,10 +28,10 @@ import org.junit.runners.model.Statement
class RequireSafetyCenterRule(private val hostTestClass: BaseHostJUnit4Test) : TestRule {
private val safetyCenterSupported: Boolean by lazy {
- executeShellCommandOrThrow("cmd safety_center supported").toBoolean()
+ shellCommandStdoutOrThrow("cmd safety_center supported").toBooleanStrict()
}
private val safetyCenterEnabled: Boolean by lazy {
- executeShellCommandOrThrow("cmd safety_center enabled").toBoolean()
+ shellCommandStdoutOrThrow("cmd safety_center enabled").toBooleanStrict()
}
override fun apply(base: Statement, description: Description): Statement {
@@ -45,13 +45,20 @@ class RequireSafetyCenterRule(private val hostTestClass: BaseHostJUnit4Test) : T
}
/** Returns the package name of Safety Center on the test device. */
- fun getSafetyCenterPackageName(): String =
- executeShellCommandOrThrow("cmd safety_center package-name")
+ fun getSafetyCenterPackageName(): String {
+ return shellCommandStdoutOrThrow("cmd safety_center package-name")
+ }
- private fun executeShellCommandOrThrow(command: String): String {
+ private fun shellCommandStdoutOrThrow(command: String): String {
val result = hostTestClass.device.executeShellV2Command(command)
if (result.status != CommandStatus.SUCCESS) {
- throw IOException("$command exited with status ${result.exitCode}")
+ throw IOException(
+ """Host-side test failed to execute adb shell command on test device.
+ |Command '$command' exited with status code ${result.exitCode}.
+ |This probably means the test device does not have a compatible version of
+ |the Permission Mainline module. Please check the test configuration."""
+ .trimMargin("|")
+ )
}
return result.stdout.trim()
}
diff --git a/tests/utils/safetycenter/AndroidManifest.xml b/tests/utils/safetycenter/AndroidManifest.xml
index 9d7c52e62..ce3724318 100644
--- a/tests/utils/safetycenter/AndroidManifest.xml
+++ b/tests/utils/safetycenter/AndroidManifest.xml
@@ -40,11 +40,25 @@
<activity android:name=".TestActivity"
android:exported="false">
- <intent-filter>
+ <intent-filter android:priority="-1">
+ <action android:name="com.android.safetycenter.testing.action.TEST_ACTIVITY"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <!-- Create an alias at higher priority, disabled. We have seen flakes where implicit
+ intents for TEST_ACTIVITY fail owing to multiple receivers, perhaps due to an older
+ CTS APK hanging around. We turn this component on (and off in tidyup) in tests, in
+ the hope of only resolving to the actively running test in these cases. -->
+ <activity-alias android:name=".TestActivityPriority"
+ android:targetActivity=".TestActivity"
+ android:enabled="false"
+ android:exported="false">
+ <intent-filter android:priority="0">
<action android:name="com.android.safetycenter.testing.action.TEST_ACTIVITY"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
- </activity>
+ </activity-alias>
<activity-alias android:name=".TestActivityExported"
android:targetActivity=".TestActivity"
@@ -54,5 +68,14 @@
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity-alias>
+
+ <service android:name=".TestNotificationListener"
+ android:label="TestNotificationListener"
+ android:exported="false"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService" />
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
index 44c0686e2..a7009b19e 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/Coroutines.kt
@@ -17,6 +17,7 @@
package com.android.safetycenter.testing
import android.util.Log
+import androidx.test.platform.app.InstrumentationRegistry
import java.time.Duration
import kotlinx.coroutines.DEBUG_PROPERTY_NAME
import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_AUTO
@@ -29,8 +30,19 @@ import kotlinx.coroutines.withTimeoutOrNull
/** A class that facilitates interacting with coroutines. */
object Coroutines {
+ /**
+ * The timeout of a test case, typically varies depending on whether the test is running
+ * locally, on pre-submit or post-submit.
+ */
+ val TEST_TIMEOUT: Duration
+ get() =
+ Duration.ofMillis(
+ InstrumentationRegistry.getArguments().getString("timeout_msec", "60000").toLong()
+ )
+
/** A long timeout, to be used for actions that are expected to complete. */
- val TIMEOUT_LONG: Duration = Duration.ofSeconds(25)
+ val TIMEOUT_LONG: Duration
+ get() = TEST_TIMEOUT.dividedBy(2)
/** A short timeout, to be used for actions that are expected not to complete. */
val TIMEOUT_SHORT: Duration = Duration.ofSeconds(1)
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/EnableSensorRule.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/EnableSensorRule.kt
new file mode 100644
index 000000000..1ed0ecbc3
--- /dev/null
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/EnableSensorRule.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.testing
+
+import android.Manifest.permission.MANAGE_SENSOR_PRIVACY
+import android.Manifest.permission.OBSERVE_SENSOR_PRIVACY
+import android.content.Context
+import android.hardware.SensorPrivacyManager
+import android.hardware.SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE
+import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
+import org.junit.Assume.assumeTrue
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * A JUnit [TestRule] to ensure a given [sensor] is enabled.
+ *
+ * This rule disables sensor privacy before a test and restores the prior state afterwards.
+ */
+class EnableSensorRule(context: Context, val sensor: Int) : TestRule {
+
+ private val sensorPrivacyManager: SensorPrivacyManager =
+ context.getSystemService(SensorPrivacyManager::class.java)!!
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ assumeTrue(
+ "Test device does not support toggling sensor $sensor",
+ supportsSensorToggle()
+ )
+ val oldSensorPrivacy = isSensorPrivacyEnabled()
+ setSensorPrivacy(false)
+ try {
+ base.evaluate()
+ } finally {
+ setSensorPrivacy(oldSensorPrivacy)
+ }
+ }
+ }
+ }
+
+ private fun supportsSensorToggle(): Boolean =
+ sensorPrivacyManager.supportsSensorToggle(sensor) &&
+ sensorPrivacyManager.supportsSensorToggle(TOGGLE_TYPE_SOFTWARE, sensor)
+
+ private fun isSensorPrivacyEnabled(): Boolean =
+ callWithShellPermissionIdentity(OBSERVE_SENSOR_PRIVACY) {
+ sensorPrivacyManager.isSensorPrivacyEnabled(TOGGLE_TYPE_SOFTWARE, sensor)
+ }
+
+ private fun setSensorPrivacy(enabled: Boolean) {
+ callWithShellPermissionIdentity(MANAGE_SENSOR_PRIVACY, OBSERVE_SENSOR_PRIVACY) {
+ sensorPrivacyManager.setSensorPrivacy(sensor, enabled)
+ }
+ }
+}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/NotificationCharacteristics.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/NotificationCharacteristics.kt
index b91c72422..177c2359c 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/NotificationCharacteristics.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/NotificationCharacteristics.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.functional.testing
+package com.android.safetycenter.testing
import android.app.Notification
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterActivityLauncher.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterActivityLauncher.kt
index 537eb7ead..40515fa33 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterActivityLauncher.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterActivityLauncher.kt
@@ -28,7 +28,6 @@ import android.os.Build.VERSION_CODES.TIRAMISU
import android.os.Bundle
import androidx.annotation.RequiresApi
import androidx.test.uiautomator.By
-import com.android.compatibility.common.util.RetryableException
import com.android.compatibility.common.util.UiAutomatorUtils2.getUiDevice
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
import com.android.safetycenter.testing.UiTestHelper.waitDisplayed
@@ -46,13 +45,14 @@ object SafetyCenterActivityLauncher {
*/
fun Context.launchSafetyCenterActivity(
intentExtras: Bundle? = null,
+ intentAction: String = ACTION_SAFETY_CENTER,
withReceiverPermission: Boolean = false,
preventTrampolineToSettings: Boolean = true,
block: () -> Unit
) {
val launchSafetyCenterIntent =
createIntent(
- ACTION_SAFETY_CENTER,
+ intentAction,
intentExtras,
preventTrampolineToSettings = preventTrampolineToSettings
)
@@ -80,19 +80,6 @@ object SafetyCenterActivityLauncher {
executeBlockAndExit(block) { waitDisplayed(By.text(entryPoint)) { it.click() } }
}
- /**
- * Launches a page in Safety Center and exits it once [block] completes, throwing a
- * [RetryableException] for any [RuntimeException] thrown by [block] to allow [RetryRule] to
- * retry the test invocation.
- */
- fun openPageAndExitAllowingRetries(entryPoint: String, block: () -> Unit) {
- try {
- openPageAndExit(entryPoint, block)
- } catch (e: Throwable) {
- throw RetryableException(e, "Exception occurred when checking a Safety Center page")
- }
- }
-
private fun createIntent(
intentAction: String,
intentExtras: Bundle?,
@@ -107,6 +94,7 @@ object SafetyCenterActivityLauncher {
return launchIntent
}
+ /** Executes the given [block] and presses the back button to exit. */
fun executeBlockAndExit(block: () -> Unit, launchActivity: () -> Unit) {
val uiDevice = getUiDevice()
uiDevice.waitForIdle()
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterEnabledChangedReceiver.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterEnabledChangedReceiver.kt
index b948dc52c..f8926caac 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterEnabledChangedReceiver.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterEnabledChangedReceiver.kt
@@ -24,8 +24,8 @@ import android.content.IntentFilter
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED
import androidx.annotation.RequiresApi
-import com.android.compatibility.common.util.SystemUtil
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.Coroutines.runBlockingWithTimeout
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
import java.time.Duration
@@ -55,20 +55,18 @@ class SafetyCenterEnabledChangedReceiver(private val context: Context) : Broadca
fun setSafetyCenterEnabledWithReceiverPermissionAndWait(
value: Boolean,
timeout: Duration = TIMEOUT_LONG
- ) =
+ ): Boolean =
callWithShellPermissionIdentity(READ_SAFETY_CENTER_STATUS) {
- setSafetyCenterEnabledWithoutReceiverPermissionAndWait(value, timeout)
+ SafetyCenterFlags.isEnabled = value
+ receiveSafetyCenterEnabledChanged(timeout)
}
fun setSafetyCenterEnabledWithoutReceiverPermissionAndWait(
value: Boolean,
- timeout: Duration = TIMEOUT_LONG
- ): Boolean {
+ ) {
SafetyCenterFlags.isEnabled = value
- if (timeout < TIMEOUT_LONG) {
- SystemUtil.waitForBroadcasts()
- }
- return receiveSafetyCenterEnabledChanged(timeout)
+ WaitForBroadcasts.waitForBroadcasts()
+ receiveSafetyCenterEnabledChanged(TIMEOUT_SHORT)
}
fun unregister() {
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
index aad979229..714565d62 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterFlags.kt
@@ -20,9 +20,7 @@ import android.Manifest.permission.READ_DEVICE_CONFIG
import android.Manifest.permission.WRITE_DEVICE_CONFIG
import android.annotation.TargetApi
import android.app.job.JobInfo
-import android.content.Context
import android.content.pm.PackageManager
-import android.content.res.Resources
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
@@ -35,6 +33,8 @@ import android.safetycenter.SafetyCenterManager.REFRESH_REASON_PERIODIC
import android.safetycenter.SafetyCenterManager.REFRESH_REASON_RESCAN_BUTTON_CLICK
import android.safetycenter.SafetyCenterManager.REFRESH_REASON_SAFETY_CENTER_ENABLED
import android.safetycenter.SafetySourceData
+import com.android.modules.utils.build.SdkLevel
+import com.android.safetycenter.testing.Coroutines.TEST_TIMEOUT
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.ShellPermissions.callWithShellPermissionIdentity
import java.time.Duration
@@ -45,7 +45,7 @@ object SafetyCenterFlags {
/** Flag that determines whether Safety Center is enabled. */
private val isEnabledFlag =
- Flag("safety_center_is_enabled", defaultValue = false, BooleanParser())
+ Flag("safety_center_is_enabled", defaultValue = SdkLevel.isAtLeastU(), BooleanParser())
/** Flag that determines whether Safety Center can send notifications. */
private val notificationsFlag =
@@ -101,13 +101,6 @@ object SafetyCenterFlags {
DurationParser()
)
- /**
- * Flag that determines whether we should show error entries for sources that timeout when
- * refreshing them.
- */
- private val showErrorEntriesOnTimeoutFlag =
- Flag("safety_center_show_error_entries_on_timeout", defaultValue = false, BooleanParser())
-
/** Flag that determines whether we should replace the IconAction of the lock screen source. */
private val replaceLockScreenIconActionFlag =
Flag("safety_center_replace_lock_screen_icon_action", defaultValue = true, BooleanParser())
@@ -116,11 +109,16 @@ object SafetyCenterFlags {
* Flag that determines the time for which a Safety Center refresh is allowed to wait for a
* source to respond to a refresh request before timing out and marking the refresh as finished,
* depending on the refresh reason.
+ *
+ * Unlike the production code, this flag is set to [TEST_TIMEOUT] for all refresh reasons by
+ * default for convenience. UI tests typically will set some data manually rather than going
+ * through a full refresh, and we don't want to timeout the refresh and potentially end up with
+ * error entries in this case (as it could lead to flakyness).
*/
private val refreshSourceTimeoutsFlag =
Flag(
"safety_center_refresh_sources_timeouts_millis",
- defaultValue = getAllRefreshTimeoutsMap(TIMEOUT_LONG),
+ defaultValue = getAllRefreshTimeoutsMap(TEST_TIMEOUT),
MapParser(IntParser(), DurationParser())
)
@@ -287,13 +285,6 @@ object SafetyCenterFlags {
MapParser(StringParser(), SetParser(StringParser(), delimiter = "|"))
)
- /**
- * Flag that determines whether background refreshes require charging in
- * [SafetyCenterBackgroundRefreshJobService]. See [JobInfo.setRequiresCharging] for details.
- */
- private val backgroundRefreshRequiresChargingFlag =
- Flag("safety_center_background_requires_charging", defaultValue = false, BooleanParser())
-
/** Every Safety Center flag. */
private val FLAGS: List<Flag<*>> =
listOf(
@@ -303,7 +294,6 @@ object SafetyCenterFlags {
notificationsMinDelayFlag,
immediateNotificationBehaviorIssuesFlag,
notificationResurfaceIntervalFlag,
- showErrorEntriesOnTimeoutFlag,
replaceLockScreenIconActionFlag,
refreshSourceTimeoutsFlag,
resolveActionTimeoutFlag,
@@ -320,14 +310,7 @@ object SafetyCenterFlags {
showSubpagesFlag,
overrideRefreshOnPageOpenSourcesFlag,
backgroundRefreshIsEnabledFlag,
- periodicBackgroundRefreshIntervalFlag,
- backgroundRefreshRequiresChargingFlag
- )
-
- /** Returns whether the device supports Safety Center. */
- fun Context.deviceSupportsSafetyCenter() =
- resources.getBoolean(
- Resources.getSystem().getIdentifier("config_enableSafetyCenter", "bool", "android")
+ periodicBackgroundRefreshIntervalFlag
)
/** A property that allows getting and setting the [isEnabledFlag]. */
@@ -348,14 +331,11 @@ object SafetyCenterFlags {
/** A property that allows getting and setting the [notificationResurfaceIntervalFlag]. */
var notificationResurfaceInterval: Duration by notificationResurfaceIntervalFlag
- /** A property that allows getting and setting the [showErrorEntriesOnTimeoutFlag]. */
- var showErrorEntriesOnTimeout: Boolean by showErrorEntriesOnTimeoutFlag
-
/** A property that allows getting and setting the [replaceLockScreenIconActionFlag]. */
var replaceLockScreenIconAction: Boolean by replaceLockScreenIconActionFlag
/** A property that allows getting and setting the [refreshSourceTimeoutsFlag]. */
- var refreshTimeouts: Map<Int, Duration> by refreshSourceTimeoutsFlag
+ private var refreshTimeouts: Map<Int, Duration> by refreshSourceTimeoutsFlag
/** A property that allows getting and setting the [resolveActionTimeoutFlag]. */
var resolveActionTimeout: Duration by resolveActionTimeoutFlag
@@ -392,15 +372,6 @@ object SafetyCenterFlags {
/** A property that allows getting and setting the [overrideRefreshOnPageOpenSourcesFlag]. */
var overrideRefreshOnPageOpenSources: Set<String> by overrideRefreshOnPageOpenSourcesFlag
- /** A property that allows getting and settings the [backgroundRefreshIsEnabledFlag]. */
- var backgroundRefreshIsEnabled: Boolean by backgroundRefreshIsEnabledFlag
-
- /** A property that allows getting and settings the [periodicBackgroundRefreshIntervalFlag]. */
- var periodicBackgroundRefreshInterval: Duration by periodicBackgroundRefreshIntervalFlag
-
- /** A property that allows getting and settings the [backgroundRefreshRequiresChargingFlag]. */
- var backgroundRefreshRequiresCharging: Boolean by backgroundRefreshRequiresChargingFlag
-
/**
* Returns a snapshot of all the Safety Center flags.
*
@@ -454,7 +425,7 @@ object SafetyCenterFlags {
/** Returns the [isEnabledFlag] value of the Safety Center flags snapshot. */
fun Properties.isSafetyCenterEnabled() =
- getBoolean(isEnabledFlag.name, /* defaultValue */ false)
+ getBoolean(isEnabledFlag.name, isEnabledFlag.defaultValue)
@TargetApi(UPSIDE_DOWN_CAKE)
private fun getAllRefreshTimeoutsMap(refreshTimeout: Duration): Map<Int, Duration> =
@@ -527,11 +498,7 @@ object SafetyCenterFlags {
.joinToString(entriesDelimiter)
}
- private class Flag<T>(
- val name: String,
- private val defaultValue: T,
- private val parser: Parser<T>
- ) {
+ private class Flag<T>(val name: String, val defaultValue: T, private val parser: Parser<T>) {
val defaultStringValue = parser.toString(defaultValue)
operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
index 5ff42e23c..31e9855ae 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestData.kt
@@ -48,7 +48,7 @@ import com.android.safetycenter.internaldata.SafetyCenterIds
import com.android.safetycenter.internaldata.SafetyCenterIssueActionId
import com.android.safetycenter.internaldata.SafetyCenterIssueId
import com.android.safetycenter.internaldata.SafetyCenterIssueKey
-import com.android.safetycenter.resources.SafetyCenterResourcesContext
+import com.android.safetycenter.resources.SafetyCenterResourcesApk
import com.android.safetycenter.testing.SafetyCenterTestConfigs.Companion.SINGLE_SOURCE_GROUP_ID
import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ACTION_ID
import com.android.safetycenter.testing.SafetySourceTestData.Companion.CRITICAL_ISSUE_ID
@@ -66,23 +66,24 @@ import java.util.Locale
@RequiresApi(TIRAMISU)
class SafetyCenterTestData(context: Context) {
- private val safetyCenterResourcesContext = SafetyCenterResourcesContext.forTests(context)
+ private val safetyCenterResourcesApk = SafetyCenterResourcesApk.forTests(context)
private val safetySourceTestData = SafetySourceTestData(context)
/**
* The [SafetyCenterStatus] used when the overall status is unknown and no scan is in progress.
*/
- val safetyCenterStatusUnknown =
- SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_title"
- ),
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_ok_review_summary"
+ val safetyCenterStatusUnknown: SafetyCenterStatus
+ get() =
+ SafetyCenterStatus.Builder(
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_ok_review_title"
+ ),
+ safetyCenterResourcesApk.getStringByName(
+ "overall_severity_level_ok_review_summary"
+ )
)
- )
- .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
- .build()
+ .setSeverityLevel(OVERALL_SEVERITY_LEVEL_UNKNOWN)
+ .build()
/**
* Returns a [SafetyCenterStatus] with one alert and the given [statusResource] and
@@ -103,7 +104,7 @@ class SafetyCenterTestData(context: Context) {
numAlerts: Int,
): SafetyCenterStatus =
SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(statusResource),
+ safetyCenterResourcesApk.getStringByName(statusResource),
getAlertString(numAlerts)
)
.setSeverityLevel(overallSeverityLevel)
@@ -117,11 +118,8 @@ class SafetyCenterTestData(context: Context) {
numTipIssues: Int,
): SafetyCenterStatus =
SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName(
- "overall_severity_level_tip_summary",
- numTipIssues
- )
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ getIcuPluralsString("overall_severity_level_tip_summary", numTipIssues)
)
.setSeverityLevel(OVERALL_SEVERITY_LEVEL_OK)
.build()
@@ -134,8 +132,8 @@ class SafetyCenterTestData(context: Context) {
numAutomaticIssues: Int,
): SafetyCenterStatus =
SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName("overall_severity_level_ok_title"),
- safetyCenterResourcesContext.getStringByName(
+ safetyCenterResourcesApk.getStringByName("overall_severity_level_ok_title"),
+ getIcuPluralsString(
"overall_severity_level_action_taken_summary",
numAutomaticIssues
)
@@ -149,7 +147,7 @@ class SafetyCenterTestData(context: Context) {
*/
fun safetyCenterStatusCritical(numAlerts: Int) =
SafetyCenterStatus.Builder(
- safetyCenterResourcesContext.getStringByName(
+ safetyCenterResourcesApk.getStringByName(
"overall_severity_level_critical_safety_warning_title"
),
getAlertString(numAlerts)
@@ -428,7 +426,7 @@ class SafetyCenterTestData(context: Context) {
private fun getIcuPluralsString(name: String, count: Int, vararg formatArgs: Any): String {
val messageFormat =
MessageFormat(
- safetyCenterResourcesContext.getStringByName(name, formatArgs),
+ safetyCenterResourcesApk.getStringByName(name, formatArgs),
Locale.getDefault()
)
val arguments = ArrayMap<String, Any>()
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestHelper.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestHelper.kt
index 82f7326fd..2902cdd6a 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestHelper.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestHelper.kt
@@ -27,6 +27,7 @@ import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceData
import android.safetycenter.config.SafetyCenterConfig
import android.safetycenter.config.SafetySource.SAFETY_SOURCE_TYPE_STATIC
+import android.util.Log
import androidx.annotation.RequiresApi
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.addOnSafetyCenterDataChangedListenerWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.clearAllSafetySourceDataForTestsWithPermission
@@ -44,7 +45,7 @@ import com.google.common.util.concurrent.MoreExecutors.directExecutor
/** A class that facilitates settings up Safety Center in tests. */
@RequiresApi(TIRAMISU)
-class SafetyCenterTestHelper(private val context: Context) {
+class SafetyCenterTestHelper(val context: Context) {
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
private val userManager = context.getSystemService(UserManager::class.java)!!
@@ -55,14 +56,17 @@ class SafetyCenterTestHelper(private val context: Context) {
* values. To be called before each test.
*/
fun setup() {
- SafetySourceReceiver.setup()
+ Log.d(TAG, "setup")
Coroutines.enableDebugging()
+ SafetySourceReceiver.setup()
+ TestActivity.enableHighPriorityAlias()
SafetyCenterFlags.setup()
setEnabled(true)
}
/** Resets the state of Safety Center. To be called after each test. */
fun reset() {
+ Log.d(TAG, "reset")
setEnabled(true)
listeners.forEach {
safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(it)
@@ -72,12 +76,14 @@ class SafetyCenterTestHelper(private val context: Context) {
safetyCenterManager.clearAllSafetySourceDataForTestsWithPermission()
safetyCenterManager.clearSafetyCenterConfigForTestsWithPermission()
resetFlags()
+ TestActivity.disableHighPriorityAlias()
SafetySourceReceiver.reset()
Coroutines.resetDebugging()
}
/** Enables or disables SafetyCenter based on [value]. */
fun setEnabled(value: Boolean) {
+ Log.d(TAG, "setEnabled to $value")
val safetyCenterConfig = safetyCenterManager.getSafetyCenterConfigWithPermission()
if (safetyCenterConfig == null) {
// No broadcasts are dispatched when toggling the flag when SafetyCenter is not
@@ -87,8 +93,8 @@ class SafetyCenterTestHelper(private val context: Context) {
SafetyCenterFlags.isEnabled = value
return
}
- val currentValue = safetyCenterManager.isSafetyCenterEnabledWithPermission()
- if (currentValue == value) {
+ if (value == isEnabled()) {
+ Log.d(TAG, "isEnabled is already $value")
return
}
setEnabledWaitingForSafetyCenterBroadcastIdle(value, safetyCenterConfig)
@@ -96,6 +102,7 @@ class SafetyCenterTestHelper(private val context: Context) {
/** Sets the given [SafetyCenterConfig]. */
fun setConfig(config: SafetyCenterConfig) {
+ Log.d(TAG, "setConfig")
require(isEnabled())
safetyCenterManager.setSafetyCenterConfigForTestsWithPermission(config)
}
@@ -107,6 +114,7 @@ class SafetyCenterTestHelper(private val context: Context) {
* initial SafetyCenter update
*/
fun addListener(skipInitialData: Boolean = true): SafetyCenterTestListener {
+ Log.d(TAG, "addListener")
require(isEnabled())
val listener = SafetyCenterTestListener()
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
@@ -126,6 +134,7 @@ class SafetyCenterTestHelper(private val context: Context) {
safetySourceData: SafetySourceData?,
safetyEvent: SafetyEvent = EVENT_SOURCE_STATE_CHANGED
) {
+ Log.d(TAG, "setData for $safetySourceId")
require(isEnabled())
safetyCenterManager.setSafetySourceDataWithPermission(
safetySourceId,
@@ -137,6 +146,8 @@ class SafetyCenterTestHelper(private val context: Context) {
/** Dismisses the [SafetyCenterIssue] for the given [safetyCenterIssueId]. */
@RequiresApi(UPSIDE_DOWN_CAKE)
fun dismissSafetyCenterIssue(safetyCenterIssueId: String) {
+ Log.d(TAG, "dismissSafetyCenterIssue")
+ require(isEnabled())
safetyCenterManager.dismissSafetyCenterIssueWithPermission(safetyCenterIssueId)
}
@@ -155,6 +166,7 @@ class SafetyCenterTestHelper(private val context: Context) {
// Wait for all ACTION_SAFETY_CENTER_ENABLED_CHANGED broadcasts to be dispatched to
// avoid them leaking onto other tests.
if (safetyCenterConfig.containsTestSource()) {
+ Log.d(TAG, "Waiting for test source enabled changed broadcast")
SafetySourceReceiver.receiveSafetyCenterEnabledChanged()
// The explicit ACTION_SAFETY_CENTER_ENABLED_CHANGED broadcast is also sent to the
// dynamically registered receivers.
@@ -166,6 +178,7 @@ class SafetyCenterTestHelper(private val context: Context) {
// 2: test finishes, 3: new test starts, 4: a test config is set, 5: broadcast from 1
// dispatched).
if (userManager.isSystemUser) {
+ Log.d(TAG, "Waiting for system enabled changed broadcast")
// The implicit broadcast is only sent to the system user.
enabledChangedReceiver.receiveSafetyCenterEnabledChanged()
}
@@ -188,4 +201,8 @@ class SafetyCenterTestHelper(private val context: Context) {
.any { it.packageName == context.packageName }
private fun isEnabled() = safetyCenterManager.isSafetyCenterEnabledWithPermission()
+
+ private companion object {
+ const val TAG: String = "SafetyCenterTestHelper"
+ }
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
index d62214843..8ce5c25d4 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestListener.kt
@@ -18,9 +18,14 @@ package com.android.safetycenter.testing
import android.os.Build.VERSION_CODES.TIRAMISU
import android.safetycenter.SafetyCenterData
+import android.safetycenter.SafetyCenterEntry
import android.safetycenter.SafetyCenterErrorDetails
import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
+import android.safetycenter.SafetyCenterStaticEntry
+import android.safetycenter.SafetyCenterStatus
+import android.text.TextUtils
import androidx.annotation.RequiresApi
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
import com.android.safetycenter.testing.Coroutines.runBlockingWithTimeout
import java.time.Duration
@@ -46,9 +51,63 @@ class SafetyCenterTestListener : OnSafetyCenterDataChangedListener {
runBlockingWithTimeout { errorChannel.send(errorDetails) }
}
- /** Waits for a [SafetyCenterData] update from SafetyCenter within the given [timeout]. */
- fun receiveSafetyCenterData(timeout: Duration = TIMEOUT_LONG) =
- runBlockingWithTimeout(timeout) { dataChannel.receive() }
+ /**
+ * Waits for a [SafetyCenterData] update from SafetyCenter within the given [timeout].
+ *
+ * Optionally, a predicate can be used to wait for the [SafetyCenterData] to be [matching].
+ */
+ fun receiveSafetyCenterData(
+ timeout: Duration = TIMEOUT_LONG,
+ matching: (SafetyCenterData) -> Boolean = { true }
+ ): SafetyCenterData =
+ runBlockingWithTimeout(timeout) {
+ var safetyCenterData = dataChannel.receive()
+ while (!matching(safetyCenterData)) {
+ safetyCenterData = dataChannel.receive()
+ }
+ safetyCenterData
+ }
+
+ /**
+ * Waits for a full Safety Center refresh to complete, where each change to the underlying
+ * [SafetyCenterData] must happen within the given [timeout].
+ *
+ * @param withErrorEntry optionally check whether we should expect the [SafetyCenterData] to
+ * have or not have at least one an error entry after the refresh completes
+ * @return the [SafetyCenterData] after the refresh completes
+ */
+ fun waitForSafetyCenterRefresh(
+ timeout: Duration = TIMEOUT_LONG,
+ withErrorEntry: Boolean? = null
+ ): SafetyCenterData {
+ receiveSafetyCenterData(timeout) {
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_DATA_FETCH_IN_PROGRESS ||
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS
+ }
+ val afterRefresh =
+ receiveSafetyCenterData(timeout) {
+ it.status.refreshStatus == SafetyCenterStatus.REFRESH_STATUS_NONE
+ }
+ if (withErrorEntry == null) {
+ return afterRefresh
+ }
+ val errorMessage =
+ SafetyCenterTestData(getApplicationContext())
+ .getRefreshErrorString(numberOfErrorEntries = 1)
+ val containsErrorEntry = afterRefresh.containsAnyEntryWithSummary(errorMessage)
+ if (withErrorEntry && !containsErrorEntry) {
+ throw AssertionError(
+ "No error entry with message: \"$errorMessage\" found in SafetyCenterData" +
+ " after refresh: $afterRefresh"
+ )
+ } else if (!withErrorEntry && containsErrorEntry) {
+ throw AssertionError(
+ "Found an error entry with message: \"$errorMessage\" in SafetyCenterData" +
+ " after refresh: $afterRefresh"
+ )
+ }
+ return afterRefresh
+ }
/**
* Waits for a [SafetyCenterErrorDetails] update from SafetyCenter within the given [timeout].
@@ -61,4 +120,23 @@ class SafetyCenterTestListener : OnSafetyCenterDataChangedListener {
dataChannel.cancel()
errorChannel.cancel()
}
+
+ private companion object {
+ fun SafetyCenterData.containsAnyEntryWithSummary(summary: CharSequence): Boolean =
+ entries().any { TextUtils.equals(it.summary, summary) } ||
+ staticEntries().any { TextUtils.equals(it.summary, summary) }
+
+ fun SafetyCenterData.entries(): List<SafetyCenterEntry> =
+ entriesOrGroups.flatMap {
+ val entry = it.entry
+ if (entry != null) {
+ listOf(entry)
+ } else {
+ it.entryGroup!!.entries
+ }
+ }
+
+ fun SafetyCenterData.staticEntries(): List<SafetyCenterStaticEntry> =
+ staticEntryGroups.flatMap { it.staticEntries }
+ }
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestRule.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestRule.kt
new file mode 100644
index 000000000..dcbc4ebe9
--- /dev/null
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetyCenterTestRule.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.testing
+
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/** A JUnit [TestRule] that performs setup and reset steps before and after Safety Center tests. */
+class SafetyCenterTestRule(
+ private val safetyCenterTestHelper: SafetyCenterTestHelper,
+ private val withNotifications: Boolean = false
+) : TestRule {
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ setup()
+ try {
+ base.evaluate()
+ } finally {
+ reset()
+ }
+ }
+ }
+ }
+
+ private fun setup() {
+ safetyCenterTestHelper.setup()
+ if (withNotifications) {
+ TestNotificationListener.setup(safetyCenterTestHelper.context)
+ }
+ }
+
+ private fun reset() {
+ safetyCenterTestHelper.reset()
+ if (withNotifications) {
+ // It is important to reset the notification listener last because it waits/ensures that
+ // all notifications have been removed before returning.
+ TestNotificationListener.reset(safetyCenterTestHelper.context)
+ }
+ }
+}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceIntentHandler.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceIntentHandler.kt
index 2bd662ee8..8386228b8 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceIntentHandler.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceIntentHandler.kt
@@ -221,7 +221,7 @@ class SafetySourceIntentHandler {
safetyEventForResponse: (Response) -> SafetyEvent
) {
val response = mutex.withLock { requestsToResponses[request] } ?: return
- val safetyEvent = safetyEventForResponse(response)
+ val safetyEvent = response.overrideSafetyEvent ?: safetyEventForResponse(response)
when (response) {
is Response.Error ->
reportSafetySourceError(request.sourceId, SafetySourceErrorDetails(safetyEvent))
@@ -270,6 +270,13 @@ class SafetySourceIntentHandler {
*/
sealed interface Response {
+ /**
+ * If non-null, the [SafetyEvent] to use when calling any applicable [SafetyCenterManager]
+ * methods.
+ */
+ val overrideSafetyEvent: SafetyEvent?
+ get() = null
+
/** Creates an error [Response]. */
object Error : Response
@@ -282,10 +289,13 @@ class SafetySourceIntentHandler {
* @param overrideBroadcastId an optional override of the broadcast id to use in the
* [SafetyEvent] sent to the [SafetyCenterManager], in case of [Request.Refresh] or
* [Request.Rescan]. This is used to simulate a misuse of the [SafetyCenterManager] APIs
+ * @param overrideSafetyEvent like [overrideBroadcastId] but allows the whole [SafetyEvent]
+ * to be override to send different types of [SafetyEvent].
*/
data class SetData(
val safetySourceData: SafetySourceData,
- val overrideBroadcastId: String? = null
+ val overrideBroadcastId: String? = null,
+ override val overrideSafetyEvent: SafetyEvent? = null
) : Response
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceReceiver.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceReceiver.kt
index 2ba87040a..29072c989 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceReceiver.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceReceiver.kt
@@ -35,8 +35,8 @@ import android.safetycenter.SafetyCenterManager
import android.safetycenter.SafetyCenterManager.ACTION_SAFETY_CENTER_ENABLED_CHANGED
import androidx.annotation.RequiresApi
import androidx.test.core.app.ApplicationProvider
-import com.android.compatibility.common.util.SystemUtil
import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_SHORT
import com.android.safetycenter.testing.Coroutines.runBlockingWithTimeout
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.dismissSafetyCenterIssueWithPermission
import com.android.safetycenter.testing.SafetyCenterApisWithShellPermissions.executeSafetyCenterIssueActionWithPermission
@@ -164,46 +164,38 @@ class SafetySourceReceiver : BroadcastReceiver() {
fun SafetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
refreshReason: Int,
- timeout: Duration = TIMEOUT_LONG,
- safetySourceIds: List<String>? = null
- ) =
+ safetySourceIds: List<String>? = null,
+ timeout: Duration = TIMEOUT_LONG
+ ): String =
callWithShellPermissionIdentity(SEND_SAFETY_CENTER_UPDATE) {
- refreshSafetySourcesWithoutReceiverPermissionAndWait(
- refreshReason,
- timeout,
- safetySourceIds
- )
+ refreshSafetySourcesWithPermission(refreshReason, safetySourceIds)
+ receiveRefreshSafetySources(timeout)
}
fun SafetyCenterManager.refreshSafetySourcesWithoutReceiverPermissionAndWait(
refreshReason: Int,
- timeout: Duration,
safetySourceIds: List<String>? = null
- ): String {
+ ) {
refreshSafetySourcesWithPermission(refreshReason, safetySourceIds)
- if (timeout < TIMEOUT_LONG) {
- SystemUtil.waitForBroadcasts()
- }
- return receiveRefreshSafetySources(timeout)
+ WaitForBroadcasts.waitForBroadcasts()
+ receiveRefreshSafetySources(TIMEOUT_SHORT)
}
fun setSafetyCenterEnabledWithReceiverPermissionAndWait(
value: Boolean,
timeout: Duration = TIMEOUT_LONG
- ) =
+ ): Boolean =
callWithShellPermissionIdentity(SEND_SAFETY_CENTER_UPDATE) {
- setSafetyCenterEnabledWithoutReceiverPermissionAndWait(value, timeout)
+ SafetyCenterFlags.isEnabled = value
+ receiveSafetyCenterEnabledChanged(timeout)
}
fun setSafetyCenterEnabledWithoutReceiverPermissionAndWait(
value: Boolean,
- timeout: Duration = TIMEOUT_LONG
- ): Boolean {
+ ) {
SafetyCenterFlags.isEnabled = value
- if (timeout < TIMEOUT_LONG) {
- SystemUtil.waitForBroadcasts()
- }
- return receiveSafetyCenterEnabledChanged(timeout)
+ WaitForBroadcasts.waitForBroadcasts()
+ receiveSafetyCenterEnabledChanged(TIMEOUT_SHORT)
}
fun SafetyCenterManager.executeSafetyCenterIssueActionWithPermissionAndWait(
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
index 97e2078e0..0dda827ee 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SafetySourceTestData.kt
@@ -425,12 +425,25 @@ class SafetySourceTestData(private val context: Context) {
.build()
/** A [PendingIntent] used by the resolving [Action] in [criticalResolvingGeneralIssue]. */
- val criticalIssueActionPendingIntent =
+ val criticalIssueActionPendingIntent = resolvingActionPendingIntent()
+
+ /**
+ * Returns a [PendingIntent] for a resolving [Action] with the given [sourceId], [sourceIssueId]
+ * and [sourceIssueActionId]. Default values are the same as those used by
+ * [criticalIssueActionPendingIntent]. *
+ */
+ fun resolvingActionPendingIntent(
+ sourceId: String = SINGLE_SOURCE_ID,
+ sourceIssueId: String = CRITICAL_ISSUE_ID,
+ sourceIssueActionId: String = CRITICAL_ISSUE_ACTION_ID
+ ) =
broadcastPendingIntent(
Intent(ACTION_RESOLVE_ACTION)
- .putExtra(EXTRA_SOURCE_ID, SINGLE_SOURCE_ID)
- .putExtra(EXTRA_SOURCE_ISSUE_ID, CRITICAL_ISSUE_ID)
- .putExtra(EXTRA_SOURCE_ISSUE_ACTION_ID, CRITICAL_ISSUE_ACTION_ID)
+ .putExtra(EXTRA_SOURCE_ID, sourceId)
+ .putExtra(EXTRA_SOURCE_ISSUE_ID, sourceIssueId)
+ .putExtra(EXTRA_SOURCE_ISSUE_ACTION_ID, sourceIssueActionId)
+ // Identifier is set because intent extras do not disambiguate PendingIntents
+ .setIdentifier(sourceId + sourceIssueId + sourceIssueActionId)
)
/** A resolving Critical [Action] */
@@ -812,13 +825,26 @@ class SafetySourceTestData(private val context: Context) {
}
/** Returns a [PendingIntent] that redirects to [intent]. */
- fun createRedirectPendingIntent(context: Context, intent: Intent): PendingIntent {
+ fun createRedirectPendingIntent(
+ context: Context,
+ intent: Intent,
+ inQuietMode: Boolean = false
+ ): PendingIntent {
val explicitIntent = Intent(intent).setPackage(context.packageName)
val redirectIntent =
if (intentResolves(context, explicitIntent)) {
explicitIntent
} else if (intentResolves(context, intent)) {
- intent
+ // We have seen some flakiness where implicit intents find multiple receivers
+ // and the ResolveActivity pops up. A test cannot handle this, so crash. Most
+ // likely the cause is other test's APKs being left hanging around by flaky
+ // test infrastructure.
+ val intentWithFlag = Intent(intent)
+ intentWithFlag.flags =
+ intentWithFlag.flags or Intent.FLAG_ACTIVITY_REQUIRE_DEFAULT
+ intentWithFlag
+ } else if (inQuietMode) {
+ explicitIntent
} else {
throw IllegalStateException("Intent doesn't resolve")
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/StatusBarNotificationWithChannel.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/StatusBarNotificationWithChannel.kt
index d9a998c3e..53ea34362 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/StatusBarNotificationWithChannel.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/StatusBarNotificationWithChannel.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.safetycenter.functional.testing
+package com.android.safetycenter.testing
import android.app.NotificationChannel
import android.service.notification.StatusBarNotification
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenter.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenter.kt
new file mode 100644
index 000000000..bfb5c4bd7
--- /dev/null
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenter.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.testing
+
+import android.content.Context
+import android.content.res.Resources
+
+/**
+ * Returns whether the device supports Safety Center according to the `config_enableSafetyCenter`
+ * boolean system resource.
+ */
+fun Context.deviceSupportsSafetyCenter(): Boolean {
+ val resId = Resources.getSystem().getIdentifier("config_enableSafetyCenter", "bool", "android")
+ return resources.getBoolean(resId)
+}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenterRule.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenterRule.kt
new file mode 100644
index 000000000..7227873ff
--- /dev/null
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/SupportsSafetyCenterRule.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.testing
+
+import android.content.Context
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * JUnit [TestRule] for on-device tests that requires Safety Center to be supported. This rule does
+ * not require Safety Center to be enabled.
+ *
+ * For tests which should only run on devices where Safety Center is not supported, instantiate with
+ * [requireSupportIs] set to `false` to invert the condition.
+ */
+class SupportsSafetyCenterRule(private val context: Context, requireSupportIs: Boolean = true) :
+ TestRule {
+
+ private val shouldSupportSafetyCenter: Boolean = requireSupportIs
+
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ val support = context.deviceSupportsSafetyCenter()
+ if (shouldSupportSafetyCenter) {
+ assumeTrue("Test device does not support Safety Center", support)
+ } else {
+ assumeFalse("Test device supports Safety Center", support)
+ }
+ base.evaluate()
+ }
+ }
+ }
+}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestActivity.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestActivity.kt
index 124f44101..eceffb74f 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestActivity.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestActivity.kt
@@ -16,9 +16,15 @@
package com.android.safetycenter.testing
import android.app.Activity
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+import android.content.pm.PackageManager.DONT_KILL_APP
import android.os.Bundle
import android.view.View
import android.widget.TextView
+import androidx.test.core.app.ApplicationProvider
/** An activity used in tests to assert the redirects. */
class TestActivity : Activity() {
@@ -32,4 +38,32 @@ class TestActivity : Activity() {
val exitButton: View? = findViewById(R.id.button)
exitButton?.setOnClickListener { finish() }
}
+
+ companion object {
+
+ /**
+ * Enable a higher-priority alias of TestActivity.
+ *
+ * <p>We have seen flakes where implicit intents for TEST_ACTIVITY fail owing to multiple
+ * receivers, perhaps due to an older CTS APK hanging around. This component should be
+ * turned on (and off in tidyup) in tests in the hope of only resolving to the actively
+ * running test in these cases.
+ */
+ fun enableHighPriorityAlias() {
+ setAliasEnabledState(COMPONENT_ENABLED_STATE_ENABLED)
+ }
+ /** @see [enableHighPriorityAlias] */
+ fun disableHighPriorityAlias() {
+ setAliasEnabledState(COMPONENT_ENABLED_STATE_DISABLED)
+ }
+ private fun setAliasEnabledState(state: Int) {
+ val name =
+ ComponentName(getApplicationContext(), TestActivity::class.java.name + "Priority")
+ getApplicationContext()
+ .packageManager
+ .setComponentEnabledSetting(name, state, DONT_KILL_APP)
+ }
+
+ private fun getApplicationContext(): Context = ApplicationProvider.getApplicationContext()
+ }
}
diff --git a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/TestNotificationListener.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt
index 113ad3b23..2b2342d7a 100644
--- a/tests/functional/safetycenter/singleuser/src/android/safetycenter/functional/testing/TestNotificationListener.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/TestNotificationListener.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package android.safetycenter.functional.testing
+package com.android.safetycenter.testing
import android.app.NotificationChannel
import android.content.ComponentName
+import android.content.Context
import android.os.ConditionVariable
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
@@ -84,15 +85,7 @@ class TestNotificationListener : NotificationListenerService() {
}
companion object {
- private const val TAG = "TestNotificationListene"
-
- private val id: String =
- "android.safetycenter.functional/" + TestNotificationListener::class.java.name
- private val componentName =
- ComponentName(
- "android.safetycenter.functional",
- TestNotificationListener::class.java.name
- )
+ private const val TAG = "SafetyCenterTestNotif"
private val connected = ConditionVariable(false)
private val disconnected = ConditionVariable(true)
@@ -132,7 +125,10 @@ class TestNotificationListener : NotificationListenerService() {
count: Int,
timeout: Duration = TIMEOUT_LONG
): List<StatusBarNotificationWithChannel> {
- return waitForNotificationsToSatisfy(timeout, description = "$count notifications") {
+ return waitForNotificationsToSatisfy(
+ timeout = timeout,
+ description = "$count notifications"
+ ) {
it.size == count
}
}
@@ -162,18 +158,46 @@ class TestNotificationListener : NotificationListenerService() {
): List<StatusBarNotificationWithChannel> {
val charsList = characteristics.toList()
return waitForNotificationsToSatisfy(
- timeout,
+ timeout = timeout,
description = "notification(s) matching characteristics $charsList"
- ) { NotificationCharacteristics.areMatching(it, charsList) }
+ ) {
+ NotificationCharacteristics.areMatching(it, charsList)
+ }
+ }
+
+ /**
+ * Waits for a success notification with the given [successMessage] after resolving an
+ * issue.
+ *
+ * Additional assertions can be made on the [StatusBarNotification] using [onNotification].
+ */
+ fun waitForSuccessNotification(
+ successMessage: String,
+ onNotification: (StatusBarNotification) -> Unit = {}
+ ) {
+ val successNotificationWithChannel =
+ waitForSingleNotificationMatching(
+ NotificationCharacteristics(
+ successMessage,
+ "",
+ actions = emptyList(),
+ )
+ )
+ val statusBarNotification = successNotificationWithChannel.statusBarNotification
+ onNotification(statusBarNotification)
+ // Cancel the notification directly to speed up the tests as it's only auto-cancelled
+ // after 10 seconds, and the teardown waits for all notifications to be cancelled to
+ // avoid having unrelated notifications leaking between test cases.
+ cancelAndWait(statusBarNotification.key, waitForIssueCache = false)
}
/**
- * Blocks until [forAtLeast] has elapsed, or throw an [AssertionError] if any notification
- * is posted or removed before then.
+ * Blocks for [TIMEOUT_SHORT], or throw an [AssertionError] if any notification is posted or
+ * removed before then.
*/
- fun waitForZeroNotificationEvents(forAtLeast: Duration = TIMEOUT_SHORT) {
+ fun waitForZeroNotificationEvents() {
val event =
- runBlockingWithTimeoutOrNull(forAtLeast) {
+ runBlockingWithTimeoutOrNull(TIMEOUT_SHORT) {
safetyCenterNotificationEvents.receive()
}
assertThat(event).isNull()
@@ -185,10 +209,6 @@ class TestNotificationListener : NotificationListenerService() {
description: String,
predicate: (List<StatusBarNotificationWithChannel>) -> Boolean
): List<StatusBarNotificationWithChannel> {
- fun formatError(notifs: List<StatusBarNotificationWithChannel>): String {
- return "Expected: $description, but the actual notifications were: $notifs"
- }
-
// First we wait at most timeout for the active notifications to satisfy the given
// predicate or otherwise we throw:
val satisfyingNotifications =
@@ -197,7 +217,11 @@ class TestNotificationListener : NotificationListenerService() {
waitForNotificationsToSatisfyAsync(predicate)
}
} catch (e: TimeoutCancellationException) {
- throw AssertionError(formatError(getSafetyCenterNotifications()), e)
+ throw AssertionError(
+ "Expected: $description, but notifications were " +
+ "${getSafetyCenterNotifications()} after waiting for $timeout",
+ e
+ )
}
// Assuming the predicate was satisfied, now we ensure it is not violated for the
@@ -208,7 +232,10 @@ class TestNotificationListener : NotificationListenerService() {
}
if (nonSatisfyingNotifications != null) {
// In this case the negated-predicate was satisfied before forAtLeast had elapsed
- throw AssertionError(formatError(nonSatisfyingNotifications))
+ throw AssertionError(
+ "Expected: $description to settle, but notifications changed to " +
+ "$nonSatisfyingNotifications within $forAtLeast"
+ )
}
return satisfyingNotifications
@@ -276,16 +303,20 @@ class TestNotificationListener : NotificationListenerService() {
/**
* Cancels a specific notification and then waits for it to be removed by the notification
* manager and marked as dismissed in Safety Center, or throws if it has not been removed
- * within [timeout].
+ * within [TIMEOUT_LONG].
*/
- fun cancelAndWait(key: String, timeout: Duration = TIMEOUT_LONG) {
+ fun cancelAndWait(key: String, waitForIssueCache: Boolean = true) {
getInstanceOrThrow().cancelNotification(key)
waitForNotificationsToSatisfy(
- timeout,
+ timeout = TIMEOUT_LONG,
description = "no notification with the key $key"
- ) { notifications -> notifications.none { it.statusBarNotification.key == key } }
+ ) { notifications ->
+ notifications.none { it.statusBarNotification.key == key }
+ }
- waitForIssueCacheToContainAnyDismissedNotification()
+ if (waitForIssueCache) {
+ waitForIssueCacheToContainAnyDismissedNotification()
+ }
}
private fun waitForIssueCacheToContainAnyDismissedNotification() {
@@ -313,10 +344,12 @@ class TestNotificationListener : NotificationListenerService() {
}
/** Runs a shell command to allow or disallow the listener. Use before and after test. */
- private fun toggleListenerAccess(allowed: Boolean) {
- // TODO(b/260335646): Try to do this using the AndroidTest.xml instead of in code
+ private fun toggleListenerAccess(context: Context, allowed: Boolean) {
+ val componentName = ComponentName(context, TestNotificationListener::class.java)
val verb = if (allowed) "allow" else "disallow"
- SystemUtil.runShellCommand("cmd notification ${verb}_listener $id")
+ SystemUtil.runShellCommand(
+ "cmd notification ${verb}_listener ${componentName.flattenToString()}"
+ )
if (allowed) {
requestRebind(componentName)
if (!connected.block(TIMEOUT_LONG.toMillis())) {
@@ -332,22 +365,29 @@ class TestNotificationListener : NotificationListenerService() {
}
/** Prepare the [TestNotificationListener] for a notification test */
- fun setup() {
- toggleListenerAccess(true)
+ fun setup(context: Context) {
+ toggleListenerAccess(context, true)
}
/** Clean up the [TestNotificationListener] after executing a notification test. */
- fun reset() {
+ fun reset(context: Context) {
waitForNotificationsToSatisfy(
forAtLeast = Duration.ZERO,
description = "all Safety Center notifications removed in tear down"
- ) { it.isEmpty() }
- toggleListenerAccess(false)
+ ) {
+ it.isEmpty()
+ }
+ toggleListenerAccess(context, false)
safetyCenterNotificationEvents.cancel()
safetyCenterNotificationEvents = Channel(capacity = Channel.UNLIMITED)
}
private fun StatusBarNotification.isSafetyCenterNotification(): Boolean =
- packageName == "android" && notification.channelId.startsWith("safety_center")
+ packageName == "android" &&
+ notification.channelId.startsWith("safety_center") &&
+ // Don't consider the grouped system notifications to be a SC notification, in some
+ // scenarios a "ranker_group" notification can remain even when there are no more
+ // notifications associated with the channel. See b/293593539 for more details.
+ tag != "ranker_group"
}
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/UiTestHelper.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/UiTestHelper.kt
index ec676e3d9..0e062692a 100644
--- a/tests/utils/safetycenter/java/com/android/safetycenter/testing/UiTestHelper.kt
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/UiTestHelper.kt
@@ -29,10 +29,11 @@ import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.StaleObjectException
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
import com.android.compatibility.common.util.SystemUtil.runShellCommand
import com.android.compatibility.common.util.UiAutomatorUtils2.getUiDevice
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
-import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
+import com.android.compatibility.common.util.UiDumpUtils
import java.time.Duration
import java.util.concurrent.TimeoutException
import java.util.regex.Pattern
@@ -46,19 +47,30 @@ object UiTestHelper {
const val MORE_ISSUES_LABEL = "More alerts"
private const val DISMISS_ISSUE_LABEL = "Dismiss"
- private val WAIT_TIMEOUT = Duration.ofSeconds(10)
- private val NOT_DISPLAYED_TIMEOUT = Duration.ofMillis(500)
+ private const val TAG = "SafetyCenterUiTestHelper"
- private val TAG = UiTestHelper::class.java.simpleName
+ private val WAIT_TIMEOUT = Duration.ofSeconds(20)
/**
- * Waits for the given [selector] to be displayed and performs the given [uiObjectAction] on it.
+ * Waits for the given [selector] to be displayed, and optionally perform a given
+ * [uiObjectAction] on it.
*/
fun waitDisplayed(selector: BySelector, uiObjectAction: (UiObject2) -> Unit = {}) {
- waitFor("$selector to be displayed", WAIT_TIMEOUT) {
- uiObjectAction(waitFindObject(selector, it.toMillis()))
- true
+ val whenToTimeout = currentElapsedRealtime() + WAIT_TIMEOUT
+ var remaining = WAIT_TIMEOUT
+ while (remaining > Duration.ZERO) {
+ getUiDevice().waitForIdle()
+ try {
+ uiObjectAction(waitFindObject(selector, remaining.toMillis()))
+ return
+ } catch (e: StaleObjectException) {
+ Log.w(TAG, "Found stale UI object, retrying", e)
+ remaining = whenToTimeout - currentElapsedRealtime()
+ }
}
+ throw UiDumpUtils.wrapWithUiDump(
+ TimeoutException("Timed out waiting for $selector to be displayed after $WAIT_TIMEOUT")
+ )
}
/** Waits for all the given [textToFind] to be displayed. */
@@ -77,16 +89,21 @@ object UiTestHelper {
/** Waits for the given [selector] not to be displayed. */
fun waitNotDisplayed(selector: BySelector) {
- waitFor("$selector not to be displayed", NOT_DISPLAYED_TIMEOUT) {
- waitFindObjectOrNull(selector, it.toMillis()) == null
+ // TODO(b/294038848): Add scrolling to make sure it is properly gone.
+ val gone = getUiDevice().wait(Until.gone(selector), WAIT_TIMEOUT.toMillis())
+ if (gone) {
+ return
}
+ throw UiDumpUtils.wrapWithUiDump(
+ TimeoutException(
+ "Timed out waiting for $selector not to be displayed after $WAIT_TIMEOUT"
+ )
+ )
}
/** Waits for all the given [textToFind] not to be displayed. */
fun waitAllTextNotDisplayed(vararg textToFind: CharSequence?) {
- for (text in textToFind) {
- if (text != null) waitNotDisplayed(By.text(text.toString()))
- }
+ waitNotDisplayed(By.text(anyOf(*textToFind)))
}
/** Waits for a button with the given [label] not to be displayed. */
@@ -101,11 +118,11 @@ object UiTestHelper {
*/
@RequiresApi(TIRAMISU)
fun waitSourceDataDisplayed(sourceData: SafetySourceData) {
- waitAllTextDisplayed(sourceData.status?.title, sourceData.status?.summary)
-
for (sourceIssue in sourceData.issues) {
waitSourceIssueDisplayed(sourceIssue)
}
+
+ waitAllTextDisplayed(sourceData.status?.title, sourceData.status?.summary)
}
/** Waits for most of the [SafetySourceIssue] information to be displayed. */
@@ -131,7 +148,7 @@ object UiTestHelper {
fun waitCollapsedIssuesDisplayed(vararg sourceIssues: SafetySourceIssue) {
waitSourceIssueDisplayed(sourceIssues.first())
waitAllTextDisplayed(MORE_ISSUES_LABEL)
- sourceIssues.asSequence().drop(1).forEach { waitSourceIssueNotDisplayed(it) }
+ waitAllTextNotDisplayed(*sourceIssues.drop(1).map { it.title }.toTypedArray())
}
/** Waits for all the [SafetySourceIssue] to be displayed with the [MORE_ISSUES_LABEL] card. */
@@ -221,35 +238,17 @@ object UiTestHelper {
}
private fun buttonSelector(label: CharSequence): BySelector {
- return By.clickable(true).text(Pattern.compile("$label|${label.toString().uppercase()}"))
+ return By.clickable(true).text(anyOf(label, label.toString().uppercase()))
}
- private fun waitFor(
- message: String,
- uiAutomatorConditionTimeout: Duration,
- uiAutomatorCondition: (Duration) -> Boolean
- ) {
- val elapsedStartMillis = SystemClock.elapsedRealtime()
- while (true) {
- getUiDevice().waitForIdle()
- val durationSinceStart =
- Duration.ofMillis(SystemClock.elapsedRealtime() - elapsedStartMillis)
- if (durationSinceStart >= WAIT_TIMEOUT) {
- break
- }
- val remainingTime = WAIT_TIMEOUT - durationSinceStart
- val uiAutomatorTimeout = minOf(uiAutomatorConditionTimeout, remainingTime)
- try {
- if (uiAutomatorCondition(uiAutomatorTimeout)) {
- return
- } else {
- Log.d(TAG, "Failed condition for $message, will retry if within timeout")
- }
- } catch (e: StaleObjectException) {
- Log.d(TAG, "StaleObjectException for $message, will retry if within timeout", e)
+ private fun anyOf(vararg anyTextToFind: CharSequence?): Pattern {
+ val regex =
+ anyTextToFind.filterNotNull().joinToString(separator = "|") {
+ Pattern.quote(it.toString())
}
- }
-
- throw TimeoutException("Timed out waiting for $message")
+ return Pattern.compile(regex)
}
+
+ private fun currentElapsedRealtime(): Duration =
+ Duration.ofMillis(SystemClock.elapsedRealtime())
}
diff --git a/tests/utils/safetycenter/java/com/android/safetycenter/testing/WaitForBroadcasts.kt b/tests/utils/safetycenter/java/com/android/safetycenter/testing/WaitForBroadcasts.kt
new file mode 100644
index 000000000..3c19ea180
--- /dev/null
+++ b/tests/utils/safetycenter/java/com/android/safetycenter/testing/WaitForBroadcasts.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 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.safetycenter.testing
+
+import android.util.Log
+import androidx.annotation.GuardedBy
+import com.android.compatibility.common.util.SystemUtil
+import com.android.safetycenter.testing.Coroutines.TIMEOUT_LONG
+import com.android.safetycenter.testing.Coroutines.runBlockingWithTimeout
+import kotlinx.coroutines.DelicateCoroutinesApi
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
+
+/** A class to help waiting on broadcasts to be processed by the system. */
+object WaitForBroadcasts {
+
+ private const val TAG: String = "WaitForBroadcasts"
+
+ private val mutex = Mutex()
+ @GuardedBy("mutex") private var currentJob: Job? = null
+
+ /**
+ * Waits for broadcasts for at most [TIMEOUT_LONG] and prints a warning if that operation timed
+ * out.
+ *
+ * The [SystemUtil.waitForBroadcasts] operation will keep on running even after the timeout as
+ * it is not interruptible. Further calls to [WaitForBroadcasts.waitForBroadcasts] will re-use
+ * the currently running [SystemUtil.waitForBroadcasts] call if it hasn't completed.
+ */
+ fun waitForBroadcasts() {
+ try {
+ runBlockingWithTimeout {
+ mutex
+ .withLock {
+ val newJob = currentJob.maybeStartNewWaitForBroadcasts()
+ currentJob = newJob
+ newJob
+ }
+ .join()
+ }
+ } catch (e: TimeoutCancellationException) {
+ Log.w(TAG, "Waiting for broadcasts timed out, proceeding anyway", e)
+ }
+ }
+
+ // We're using a GlobalScope here as there doesn't seem to be a straightforward way to timeout
+ // and interrupt the waitForBroadcasts() call. Given it's uninterruptible, we'd rather just have
+ // at most one globally-bound waitForBroadcasts() call running at any given time.
+ @OptIn(DelicateCoroutinesApi::class)
+ private fun Job?.maybeStartNewWaitForBroadcasts(): Job =
+ if (this != null && isActive) {
+ this
+ } else {
+ GlobalScope.launch(Dispatchers.IO) { SystemUtil.waitForBroadcasts() }
+ }
+}