summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/AndroidManifest.xml13
-rw-r--r--PermissionController/TEST_MAPPING21
-rw-r--r--PermissionController/res/drawable-v34/ic_lock_closed.xml28
-rw-r--r--PermissionController/res/layout-v34/enhanced_confirmation_dialog.xml69
-rw-r--r--PermissionController/res/layout/request_role_item.xml5
-rw-r--r--PermissionController/res/values-af-v34/strings.xml6
-rw-r--r--PermissionController/res/values-am-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ar-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ar/strings.xml4
-rw-r--r--PermissionController/res/values-as-v34/strings.xml6
-rw-r--r--PermissionController/res/values-az-v34/strings.xml6
-rw-r--r--PermissionController/res/values-b+sr+Latn-v34/strings.xml6
-rw-r--r--PermissionController/res/values-b+sr+Latn/strings.xml2
-rw-r--r--PermissionController/res/values-be-v34/strings.xml6
-rw-r--r--PermissionController/res/values-bg-v34/strings.xml6
-rw-r--r--PermissionController/res/values-bn-v34/strings.xml6
-rw-r--r--PermissionController/res/values-bs-v34/strings.xml6
-rw-r--r--PermissionController/res/values-bs/strings.xml2
-rw-r--r--PermissionController/res/values-ca-v34/strings.xml6
-rw-r--r--PermissionController/res/values-cs-v34/strings.xml6
-rw-r--r--PermissionController/res/values-cs/strings.xml2
-rw-r--r--PermissionController/res/values-da-v34/strings.xml6
-rw-r--r--PermissionController/res/values-de-v34/strings.xml6
-rw-r--r--PermissionController/res/values-de/strings.xml2
-rw-r--r--PermissionController/res/values-el-v34/strings.xml6
-rw-r--r--PermissionController/res/values-en-rAU-v34/strings.xml6
-rw-r--r--PermissionController/res/values-en-rCA-v34/strings.xml6
-rw-r--r--PermissionController/res/values-en-rGB-v34/strings.xml6
-rw-r--r--PermissionController/res/values-en-rIN-v34/strings.xml6
-rw-r--r--PermissionController/res/values-en-rXC-v34/strings.xml6
-rw-r--r--PermissionController/res/values-es-rUS-v34/strings.xml6
-rw-r--r--PermissionController/res/values-es-rUS/strings.xml4
-rw-r--r--PermissionController/res/values-es-v34/strings.xml6
-rw-r--r--PermissionController/res/values-et-v34/strings.xml6
-rw-r--r--PermissionController/res/values-eu-v34/strings.xml6
-rw-r--r--PermissionController/res/values-fa-v34/strings.xml6
-rw-r--r--PermissionController/res/values-fa/strings.xml12
-rw-r--r--PermissionController/res/values-fi-v34/strings.xml6
-rw-r--r--PermissionController/res/values-fr-rCA-v34/strings.xml6
-rw-r--r--PermissionController/res/values-fr-v34/strings.xml6
-rw-r--r--PermissionController/res/values-gl-v34/strings.xml6
-rw-r--r--PermissionController/res/values-gu-v34/strings.xml6
-rw-r--r--PermissionController/res/values-hi-v34/strings.xml6
-rw-r--r--PermissionController/res/values-hi/strings.xml2
-rw-r--r--PermissionController/res/values-hr-v34/strings.xml6
-rw-r--r--PermissionController/res/values-hu-v34/strings.xml6
-rw-r--r--PermissionController/res/values-hy-v34/strings.xml6
-rw-r--r--PermissionController/res/values-hy/strings.xml2
-rw-r--r--PermissionController/res/values-in-v34/strings.xml6
-rw-r--r--PermissionController/res/values-is-v34/strings.xml6
-rw-r--r--PermissionController/res/values-it-v34/strings.xml6
-rw-r--r--PermissionController/res/values-it/strings.xml8
-rw-r--r--PermissionController/res/values-iw-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ja-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ka-v34/strings.xml6
-rw-r--r--PermissionController/res/values-kk-v34/strings.xml6
-rw-r--r--PermissionController/res/values-km-v34/strings.xml6
-rw-r--r--PermissionController/res/values-kn-v34/strings.xml6
-rw-r--r--PermissionController/res/values-kn/strings.xml2
-rw-r--r--PermissionController/res/values-ko-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ky-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ky/strings.xml2
-rw-r--r--PermissionController/res/values-lo-v34/strings.xml6
-rw-r--r--PermissionController/res/values-lt-v34/strings.xml6
-rw-r--r--PermissionController/res/values-lv-v34/strings.xml6
-rw-r--r--PermissionController/res/values-mk-v34/strings.xml6
-rw-r--r--PermissionController/res/values-mk/strings.xml4
-rw-r--r--PermissionController/res/values-ml-v34/strings.xml6
-rw-r--r--PermissionController/res/values-mn-v34/strings.xml6
-rw-r--r--PermissionController/res/values-mn/strings.xml4
-rw-r--r--PermissionController/res/values-mr-v34/strings.xml6
-rw-r--r--PermissionController/res/values-mr/strings.xml2
-rw-r--r--PermissionController/res/values-ms-v34/strings.xml6
-rw-r--r--PermissionController/res/values-my-v34/strings.xml6
-rw-r--r--PermissionController/res/values-my/strings.xml4
-rw-r--r--PermissionController/res/values-nb-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ne-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ne/strings.xml4
-rw-r--r--PermissionController/res/values-nl-v34/strings.xml6
-rw-r--r--PermissionController/res/values-or-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pa-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pl-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pl/strings.xml2
-rw-r--r--PermissionController/res/values-pt-rBR-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pt-rBR/strings.xml4
-rw-r--r--PermissionController/res/values-pt-rPT-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pt-v34/strings.xml6
-rw-r--r--PermissionController/res/values-pt/strings.xml4
-rw-r--r--PermissionController/res/values-ro-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ru-v34/strings.xml6
-rw-r--r--PermissionController/res/values-si-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sk-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sl-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sq-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sr-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sr/strings.xml2
-rw-r--r--PermissionController/res/values-sv-v34/strings.xml6
-rw-r--r--PermissionController/res/values-sw-v34/strings.xml6
-rw-r--r--PermissionController/res/values-ta-v34/strings.xml6
-rw-r--r--PermissionController/res/values-te-v34/strings.xml6
-rw-r--r--PermissionController/res/values-th-v34/strings.xml6
-rw-r--r--PermissionController/res/values-tl-v34/strings.xml6
-rw-r--r--PermissionController/res/values-tr-v34/strings.xml6
-rw-r--r--PermissionController/res/values-uk-v34/strings.xml8
-rw-r--r--PermissionController/res/values-ur-v34/strings.xml6
-rw-r--r--PermissionController/res/values-uz-v34/strings.xml6
-rw-r--r--PermissionController/res/values-uz/strings.xml6
-rw-r--r--PermissionController/res/values-v34/dimens.xml7
-rw-r--r--PermissionController/res/values-v34/strings.xml13
-rw-r--r--PermissionController/res/values-v34/styles.xml11
-rw-r--r--PermissionController/res/values-vi-v34/strings.xml6
-rw-r--r--PermissionController/res/values-watch/strings.xml21
-rw-r--r--PermissionController/res/values-zh-rCN-v34/strings.xml6
-rw-r--r--PermissionController/res/values-zh-rHK-v34/strings.xml6
-rw-r--r--PermissionController/res/values-zh-rTW-v34/strings.xml6
-rw-r--r--PermissionController/res/values-zu-v34/strings.xml6
-rw-r--r--PermissionController/res/values/dimens.xml1
-rw-r--r--PermissionController/res/values/strings.xml3
-rw-r--r--PermissionController/res/values/styles.xml1
-rw-r--r--PermissionController/res/xml/roles.xml10
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java67
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Role.java78
-rw-r--r--PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialog.java79
-rw-r--r--PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogHelper.java58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java102
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Haptics.kt292
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Rotary.kt1187
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/RotaryVelocityTracker.kt47
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/CheckableLinearLayout.java10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java192
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreference.java13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreferenceMixin.java103
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/TwoTargetPreference.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java18
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java25
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java14
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt36
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java60
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/utils/UiUtils.java26
-rw-r--r--SafetyCenter/Resources/res/values-af-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-am-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ar-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-as-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-az-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-be-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-bg-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-bn-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-bs-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ca-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-cs-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-da-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-de-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-el-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-es-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-et-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-eu-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-fa-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-fi-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-fr-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-gl-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-gu-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-hi-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-hr-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-hu-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-hy-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-in-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-is-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-it-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-iw-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ja-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ka-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-kk-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-km-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-kn-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ko-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ky-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-lo-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-lt-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-lv-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-mk-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ml-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-mn-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-mr-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ms-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-my-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-nb-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ne-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-nl-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-or-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-pa-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-pl-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-pt-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ro-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ru-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-si-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sk-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sl-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sq-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sr-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sv-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-sw-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ta-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-te-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-th-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-tl-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-tr-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-uk-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-ur-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-uz-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-vi-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml1
-rw-r--r--SafetyCenter/Resources/res/values-zu-v35/strings.xml1
-rw-r--r--flags/flags.aconfig3
-rw-r--r--framework-s/api/module-lib-current.txt1
-rw-r--r--framework-s/java/android/app/ecm/EnhancedConfirmationManager.java10
-rw-r--r--framework-s/java/android/app/role/IRoleManager.aidl2
-rw-r--r--framework-s/java/android/app/role/RoleManager.java22
-rw-r--r--service/Android.bp1
-rw-r--r--service/java/com/android/ecm/EnhancedConfirmationService.java33
-rw-r--r--service/java/com/android/role/RoleService.java27
-rw-r--r--service/java/com/android/safetycenter/UserProfileGroup.java2
-rw-r--r--tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt283
-rw-r--r--tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java9
-rw-r--r--tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt2
-rw-r--r--tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java7
-rw-r--r--tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt56
-rw-r--r--tests/cts/permissionpolicy/Android.bp2
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml87
-rw-r--r--tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml6
-rw-r--r--tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml3
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt15
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt13
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt130
-rw-r--r--tests/cts/role/Android.bp2
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleManagerTest.java50
263 files changed, 3568 insertions, 642 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 234430100..4bd7720d0 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -283,6 +283,19 @@
</intent-filter>
</activity>
+ <activity android:name="com.android.permissioncontroller.ecm.EnhancedConfirmationDialog"
+ android:theme="@style/GrantPermissions.FilterTouches"
+ android:excludeFromRecents="true"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:permission="android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES"
+ android:enabled="@bool/is_at_least_v">
+ <intent-filter android:priority="1">
+ <action android:name="android.app.ecm.action.SHOW_ECM_RESTRICTED_SETTING_DIALOG" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<activity android:name="com.android.permissioncontroller.permission.ui.v34.PermissionRationaleActivity"
android:configChanges="keyboardHidden|screenSize"
android:windowSoftInputMode="stateAlwaysHidden|adjustNothing"
diff --git a/PermissionController/TEST_MAPPING b/PermissionController/TEST_MAPPING
index a7f2aec54..084670e76 100644
--- a/PermissionController/TEST_MAPPING
+++ b/PermissionController/TEST_MAPPING
@@ -49,6 +49,18 @@
"file_patterns": ["res/xml/roles\\.xml"]
},
{
+ "name": "PermissionControllerMockingTests[com.google.android.permission.apex]",
+ "options": [
+ {
+ "include-filter": "com.android.permissioncontroller.tests.mocking.role.model.RoleParserTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ],
+ "file_patterns": ["res/xml/roles\\.xml"]
+ },
+ {
"name": "PermissionUiTestCases[com.google.android.permission.apex]",
"options": [
{
@@ -108,6 +120,15 @@
"file_patterns": ["res/xml/roles\\.xml"]
},
{
+ "name": "PermissionControllerMockingTests[com.google.android.permission.apex]",
+ "options": [
+ {
+ "include-filter": "com.android.permissioncontroller.tests.mocking.role.model.RoleParserTest"
+ }
+ ],
+ "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
diff --git a/PermissionController/res/drawable-v34/ic_lock_closed.xml b/PermissionController/res/drawable-v34/ic_lock_closed.xml
new file mode 100644
index 000000000..e61a2d4a5
--- /dev/null
+++ b/PermissionController/res/drawable-v34/ic_lock_closed.xml
@@ -0,0 +1,28 @@
+<!--
+ Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,8h-1.5V5.5C16.5,3.01 14.49,1 12,1S7.5,3.01 7.5,5.5V8H6c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V10C20,8.9 19.1,8 18,8zM9.5,5.5C9.5,4.12 10.62,3 12,3c1.38,0 2.5,1.12 2.5,2.5V8h-5V5.5zM18,20H6V10h1.5h9H18V20z"/>
+</vector>
diff --git a/PermissionController/res/layout-v34/enhanced_confirmation_dialog.xml b/PermissionController/res/layout-v34/enhanced_confirmation_dialog.xml
new file mode 100644
index 000000000..57dbbfd01
--- /dev/null
+++ b/PermissionController/res/layout-v34/enhanced_confirmation_dialog.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/enhanced_confirmation_dialog_padding"
+ android:paddingStart="@dimen/enhanced_confirmation_dialog_padding"
+ android:paddingEnd="@dimen/enhanced_confirmation_dialog_padding"
+ android:paddingBottom="@dimen/enhanced_confirmation_dialog_padding_bottom"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:paddingBottom="@dimen/enhanced_confirmation_dialog_title_bottom_padding">
+ <ImageView
+ android:id="@+id/enhanced_confirmation_icon"
+ android:layout_width="@dimen/enhanced_confirmation_dialog_icon_size"
+ android:layout_height="@dimen/enhanced_confirmation_dialog_icon_size"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_lock_closed"
+ android:tint="?android:attr/colorAccent"
+ android:contentDescription="@null"/>
+ <TextView
+ android:id="@+id/enhanced_confirmation_dialog_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:gravity="center_horizontal"
+ android:text="@string/enhanced_confirmation_dialog_title"
+ android:textAppearance="@style/TextAppearance.EnhancedConfirmationDialogHeadline"/>
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fadeScrollbars="false">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/enhanced_confirmation_dialog_desc"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.EnhancedConfirmationDialogMessage"
+ android:maxLength="200"
+ android:gravity="center_horizontal"
+ android:autoLink="email|phone|web"
+ android:text="@string/enhanced_confirmation_dialog_desc"
+ android:textColor="?android:attr/textColorSecondary"/>
+ </LinearLayout>
+ </ScrollView>
+</LinearLayout>
diff --git a/PermissionController/res/layout/request_role_item.xml b/PermissionController/res/layout/request_role_item.xml
index d7d142289..39e458aa2 100644
--- a/PermissionController/res/layout/request_role_item.xml
+++ b/PermissionController/res/layout/request_role_item.xml
@@ -24,28 +24,23 @@
<ImageView
android:id="@+id/icon"
- android:duplicateParentState="true"
style="@style/RequestRoleItemIcon" />
<LinearLayout
android:id="@+id/title_and_subtitle"
- android:duplicateParentState="true"
style="@style/RequestRoleItemTitleLayout">
<TextView
android:id="@+id/title"
- android:duplicateParentState="true"
style="@style/RequestRoleItemTitleText" />
<TextView
android:id="@+id/subtitle"
- android:duplicateParentState="true"
style="@style/RequestRoleItemSubtitleText" />
</LinearLayout>
<RadioButton
android:clickable="false"
- android:duplicateParentState="true"
android:focusable="false"
style="@style/RequestRoleItemRadioButton" />
</com.android.permissioncontroller.role.ui.CheckableLinearLayout>
diff --git a/PermissionController/res/values-af-v34/strings.xml b/PermissionController/res/values-af-v34/strings.xml
index db69a7032..d146d67f8 100644
--- a/PermissionController/res/values-af-v34/strings.xml
+++ b/PermissionController/res/values-af-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Liggingtoegang"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"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="6846532794702613851">"Vir apps en dienste"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-am-v34/strings.xml b/PermissionController/res/values-am-v34/strings.xml
index 52f5188ba..26d30f902 100644
--- a/PermissionController/res/values-am-v34/strings.xml
+++ b/PermissionController/res/values-am-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"የአካባቢ መዳረሻ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ለመተግበሪያዎች እና አገልግሎቶች። ይህ ቅንብር ከጠፋ እርስዎ ወደ አንድ የአደጋ ጊዜ ቁጥር ሲደውሉ የማይክሮፎን ውሂብ አሁንም ሊጋራ ይችላል"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ለመተግበሪያዎች እና አገልግሎቶች"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ar-v34/strings.xml b/PermissionController/res/values-ar-v34/strings.xml
index 5a0d25e63..41db873d4 100644
--- a/PermissionController/res/values-ar-v34/strings.xml
+++ b/PermissionController/res/values-ar-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"الوصول إلى الموقع الجغرافي"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"للتطبيقات والخدمات: إذا كان هذا الخيار غير مفعّل، ستستمر إمكانية مشاركة بيانات الميكروفون عند الاتصال برقم طوارئ."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"للتطبيقات والخدمات"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index 445c7af55..e9af66b78 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -351,7 +351,7 @@
<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>
@@ -508,7 +508,7 @@
<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_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>
diff --git a/PermissionController/res/values-as-v34/strings.xml b/PermissionController/res/values-as-v34/strings.xml
index 219f79370..72cca7692 100644
--- a/PermissionController/res/values-as-v34/strings.xml
+++ b/PermissionController/res/values-as-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"অৱস্থানৰ এক্সেছ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"এপ্‌ আৰু সেৱাৰ বাবে। এই ছেটিংটো অফ হৈ থাকিলে, আপুনি কোনো জৰুৰীকালীন নম্বৰলৈ কল কৰিলে মাইক্ৰ’ফ’নৰ ডেটা তথাপি শ্বেয়াৰ কৰা হ’ব পাৰে"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"এপ্‌ আৰু সেৱাৰ বাবে"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-az-v34/strings.xml b/PermissionController/res/values-az-v34/strings.xml
index 7e403dadc..90d1c3ff0 100644
--- a/PermissionController/res/values-az-v34/strings.xml
+++ b/PermissionController/res/values-az-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Məkana giriş"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Tətbiq və xidmətlər üçün. Bu ayar deaktivdirsə, təcili nömrəyə zəng etdikdə mikrofon datası yenə də paylaşıla bilər"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Tətbiq və xidmətlər üçün"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-b+sr+Latn-v34/strings.xml b/PermissionController/res/values-b+sr+Latn-v34/strings.xml
index d5bf45128..e19ebcb8f 100644
--- a/PermissionController/res/values-b+sr+Latn-v34/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Pristup lokaciji"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Za aplikacije i usluge. Ako je ovo podešavanje isključeno, podaci mikrofona mogu i dalje da se dele kada pozovete broj za hitne slučajeve"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Za aplikacije i usluge"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml
index e14ff1a67..1a7ab5b3b 100644
--- a/PermissionController/res/values-b+sr+Latn/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"beleške"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Podrazumevana aplikacija Novčanik"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Aplikacija Novčanik"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Aplikacije Novčanik mogu da čuvaju vaše kreditne kartice i kartice lojalnosti, ključeve od automobila i druge stvari kako bi vam pomogli u različitim oblicima transakcija."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Aplikacije Novčanik mogu da čuvaju vaše kreditne kartice i kartice lojalnosti, ključeve od automobila i druge stvari kako bi vam pomogli pri različitim transakcijama."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Želite da podesite <xliff:g id="APP_NAME">%1$s</xliff:g> kao podrazumevanu aplikaciju Novčanik?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nije potrebna nijedna dozvola"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Trenutno podrazumevana"</string>
diff --git a/PermissionController/res/values-be-v34/strings.xml b/PermissionController/res/values-be-v34/strings.xml
index 330681ded..6c4c30d5d 100644
--- a/PermissionController/res/values-be-v34/strings.xml
+++ b/PermissionController/res/values-be-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Доступ да даных геалакацыі"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Для праграм і сэрвісаў. Нават калі гэта налада выключана, даныя з мікрафона будуць абагульвацца падчас выкліку нумара экстраннай службы"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Для праграм і сэрвісаў"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-bg-v34/strings.xml b/PermissionController/res/values-bg-v34/strings.xml
index 33b3a52f0..73da7cd73 100644
--- a/PermissionController/res/values-bg-v34/strings.xml
+++ b/PermissionController/res/values-bg-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Достъп до местоположението"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"За приложения и услуги. Ако тази настройка е изключена, данните от микрофона пак може да бъдат споделени, когато се обадите на номер за спешни случаи"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"За приложения и услуги"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-bn-v34/strings.xml b/PermissionController/res/values-bn-v34/strings.xml
index c93980dd1..ab44ba1f2 100644
--- a/PermissionController/res/values-bn-v34/strings.xml
+++ b/PermissionController/res/values-bn-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"লোকেশন অ্যাক্সেস করা"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"অ্যাপ ও পরিষেবার জন্য। আপনি কোনও জরুরি নম্বরে কল করলে, এই সেটিং বন্ধ করা থাকলেও, মাইক্রোফোনের ডেটা শেয়ার করা হতে পারে"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"অ্যাপ ও পরিষেবার জন্য"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-bs-v34/strings.xml b/PermissionController/res/values-bs-v34/strings.xml
index e2b8445df..9d66cc88b 100644
--- a/PermissionController/res/values-bs-v34/strings.xml
+++ b/PermissionController/res/values-bs-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Pristup lokaciji"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Za aplikacije i usluge. Ako je ova postavka isključena, podaci mikrofona se i dalje mogu dijeliti kada pozovete broj za hitne slučajeve"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Za aplikacije i usluge"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml
index df621c98f..7fe697739 100644
--- a/PermissionController/res/values-bs/strings.xml
+++ b/PermissionController/res/values-bs/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"bilješke"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Zadana aplikacija za novčanik"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Aplikacija za novčanik"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Aplikacije za novčanik mogu pohranjivati kreditne kartice, kartice lojalnosti, ključeve automobila i druge stvari da vam pomognu prilikom raznih oblika transakcija."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Aplikacije za novčanik mogu pohranjivati kreditne kartice, kartice lojalnosti, ključeve automobila i druge stvari da vam pomognu pri raznim vrstama transakcija."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Postaviti aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> kao zadanu aplikaciju za novčanik?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nije potrebno odobrenje"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Trenutno zadano"</string>
diff --git a/PermissionController/res/values-ca-v34/strings.xml b/PermissionController/res/values-ca-v34/strings.xml
index 8aad7b657..0869920ff 100644
--- a/PermissionController/res/values-ca-v34/strings.xml
+++ b/PermissionController/res/values-ca-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Accés a la ubicació"</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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-cs-v34/strings.xml b/PermissionController/res/values-cs-v34/strings.xml
index b7e982b21..d333aaa50 100644
--- a/PermissionController/res/values-cs-v34/strings.xml
+++ b/PermissionController/res/values-cs-v34/strings.xml
@@ -24,4 +24,10 @@
<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í, data z mikrofonu bude možné nadále sdílet"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Aplikace a služby"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 30be5cf67..9a0c44944 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"poznámky"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Výchozí aplikace typu peněženka"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Aplikace typu peněženka"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Aplikace typu peněženka můžou uložit vaše platební a věrnostní karty, klíče od auta a další věci, a usnadnit vám tam různé transakce."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Aplikace typu peněženka můžou uložit vaše platební a věrnostní karty, klíče od auta a další věci, a usnadnit vám různé transakce."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Nastavit aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g> jako výchozí peněženku?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nejsou potřeba žádná oprávnění"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Aktuálně výchozí"</string>
diff --git a/PermissionController/res/values-da-v34/strings.xml b/PermissionController/res/values-da-v34/strings.xml
index 5777a6832..bc60ca8f3 100644
--- a/PermissionController/res/values-da-v34/strings.xml
+++ b/PermissionController/res/values-da-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Lokationsadgang"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apps og tjenester. Hvis denne indstilling er deaktiveret, deles mikrofondata muligvis stadig, når du ringer til et alarmnummer"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apps og tjenester"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-de-v34/strings.xml b/PermissionController/res/values-de-v34/strings.xml
index ed699cce3..b4d09f0af 100644
--- a/PermissionController/res/values-de-v34/strings.xml
+++ b/PermissionController/res/values-de-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Standortzugriff"</string>
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-de/strings.xml b/PermissionController/res/values-de/strings.xml
index b8864f907..9534ff31d 100644
--- a/PermissionController/res/values-de/strings.xml
+++ b/PermissionController/res/values-de/strings.xml
@@ -351,7 +351,7 @@
<string name="accessibility_service_dialog_bottom_text_multiple" msgid="7009848932395519852">"Diese Apps können deinen Bildschirm, deine Aktionen und deine Eingaben sehen, Aktionen ausführen und den Bildschirm steuern."</string>
<string name="role_assistant_label" msgid="4727586018198208128">"Standard-App digit. Assistent"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"App für digitalen Assistenten"</string>
- <string name="role_assistant_description" msgid="6622458130459922952">"Assistent-Apps können dir bei bestimmten Dingen helfen. Dazu greifen sie auf die Informationen zu, die aktuell auf deinem Bildschirm angezeigt werden. Damit sie dir eine umfassende Hilfe sind, unterstützen einige Apps sowohl Launcher- als auch Spracheingabedienste."</string>
+ <string name="role_assistant_description" msgid="6622458130459922952">"Assistent-Apps können dir bei bestimmten Dingen helfen. Dazu greifen sie auf die Informationen zu, die aktuell auf deinem Bildschirm angezeigt werden. Einige Apps unterstützen sowohl Launcher- als auch Spracheingabedienste."</string>
<string name="role_browser_label" msgid="2877796144554070207">"Standard-Browser-App"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"Browser-App"</string>
<string name="role_browser_description" msgid="3465253637499842671">"Apps, mit denen du auf das Internet zugreifen kannst und die die entsprechende Seite öffnen, wenn du auf einen Link tippst"</string>
diff --git a/PermissionController/res/values-el-v34/strings.xml b/PermissionController/res/values-el-v34/strings.xml
index 0c8541787..c2bead230 100644
--- a/PermissionController/res/values-el-v34/strings.xml
+++ b/PermissionController/res/values-el-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Πρόσβαση στην τοποθεσία"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Για εφαρμογές και υπηρεσίες. Εάν είναι απενεργοποιημένη αυτή η ρύθμιση, τα δεδομένα μικροφώνου ενδέχεται να κοινοποιούνται όταν καλείτε έναν αριθμό έκτακτης ανάγκης."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Για εφαρμογές και υπηρεσίες"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-en-rAU-v34/strings.xml b/PermissionController/res/values-en-rAU-v34/strings.xml
index 4800f8a91..0b3ecab76 100644
--- a/PermissionController/res/values-en-rAU-v34/strings.xml
+++ b/PermissionController/res/values-en-rAU-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Location access"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apps and services"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-en-rCA-v34/strings.xml b/PermissionController/res/values-en-rCA-v34/strings.xml
index 4800f8a91..0b3ecab76 100644
--- a/PermissionController/res/values-en-rCA-v34/strings.xml
+++ b/PermissionController/res/values-en-rCA-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Location access"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apps and services"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-en-rGB-v34/strings.xml b/PermissionController/res/values-en-rGB-v34/strings.xml
index 4800f8a91..0b3ecab76 100644
--- a/PermissionController/res/values-en-rGB-v34/strings.xml
+++ b/PermissionController/res/values-en-rGB-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Location access"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apps and services"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-en-rIN-v34/strings.xml b/PermissionController/res/values-en-rIN-v34/strings.xml
index 4800f8a91..0b3ecab76 100644
--- a/PermissionController/res/values-en-rIN-v34/strings.xml
+++ b/PermissionController/res/values-en-rIN-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Location access"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apps and services"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-en-rXC-v34/strings.xml b/PermissionController/res/values-en-rXC-v34/strings.xml
index 525a410b1..78ee08303 100644
--- a/PermissionController/res/values-en-rXC-v34/strings.xml
+++ b/PermissionController/res/values-en-rXC-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎Location access‎‏‎‎‏‎"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎For apps and services. If this setting is off, microphone data may still be shared when you call an emergency number‎‏‎‎‏‎"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎For apps and services‎‏‎‎‏‎"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-es-rUS-v34/strings.xml b/PermissionController/res/values-es-rUS-v34/strings.xml
index e180c0b7c..aa9cc1933 100644
--- a/PermissionController/res/values-es-rUS-v34/strings.xml
+++ b/PermissionController/res/values-es-rUS-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acceso a la ubicación"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"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="6846532794702613851">"Para apps y servicios"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml
index 30dc57425..320e5bf0f 100644
--- a/PermissionController/res/values-es-rUS/strings.xml
+++ b/PermissionController/res/values-es-rUS/strings.xml
@@ -403,7 +403,7 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"App de notas"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Apps que te permiten tomar notas en tu dispositivo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notas"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"App de billetera predet."</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Billetera predeterminada"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"App de billetera"</string>
<string name="role_wallet_description" msgid="3726535836165949838">"Las apps de billetera pueden almacenar tus tarjetas de crédito y lealtad, las llaves de tu vehículo y otros elementos para ayudarte con los diferentes tipos de transacciones."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"¿Quieres configurar <xliff:g id="APP_NAME">%1$s</xliff:g> como tu app de billetera predeterminada?"</string>
@@ -508,7 +508,7 @@
<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>
<string name="permgrouprequest_device_aware_activityRecognition" msgid="3408326850847755759">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a la actividad física en tu &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
- <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>
+ <string name="permgrouprequest_camera" msgid="5123097035410002594">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tome fotos y grabe videos?"</string>
<string name="permgrouprequest_device_aware_camera" msgid="3525106924487608868">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tome fotos y grabe videos en tu &lt;b&gt;<xliff:g id="DEVICE">%2$s</xliff:g>&lt;/b&gt;?"</string>
<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>
diff --git a/PermissionController/res/values-es-v34/strings.xml b/PermissionController/res/values-es-v34/strings.xml
index 8253d9b47..2b45b30c5 100644
--- a/PermissionController/res/values-es-v34/strings.xml
+++ b/PermissionController/res/values-es-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acceso a la ubicación"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para aplicaciones y servicios. Aunque este ajuste esté desactivado, se pueden compartir datos del micrófono si llamas a un número de emergencia."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para aplicaciones y servicios"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-et-v34/strings.xml b/PermissionController/res/values-et-v34/strings.xml
index 4476aecdd..1c157864d 100644
--- a/PermissionController/res/values-et-v34/strings.xml
+++ b/PermissionController/res/values-et-v34/strings.xml
@@ -24,4 +24,10 @@
<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="location_settings_subtitle" msgid="6846532794702613851">"Rakenduste ja teenuste jaoks"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-eu-v34/strings.xml b/PermissionController/res/values-eu-v34/strings.xml
index 5b1882738..a8767ff1f 100644
--- a/PermissionController/res/values-eu-v34/strings.xml
+++ b/PermissionController/res/values-eu-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Kokapena erabiltzeko baimena"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Aplikazio eta zerbitzuetarako. Ezarpena desaktibatuta badago ere, baliteke mikrofonoaren bidez lortutako datuak partekatzea larrialdietarako zenbaki batera deitzean."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Aplikazio eta zerbitzuetarako"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-fa-v34/strings.xml b/PermissionController/res/values-fa-v34/strings.xml
index de8036122..68b13b979 100644
--- a/PermissionController/res/values-fa-v34/strings.xml
+++ b/PermissionController/res/values-fa-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"دسترسی به مکان"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"برای برنامه‌ها و سرویس‌ها. اگر این تنظیم خاموش باشد، ممکن است وقتی با شماره تلفنی اضطراری تماس می‌گیرید داده‌های میکروفون همچنان هم‌رسانی شود"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"برای برنامه‌ها و سرویس‌ها"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-fa/strings.xml b/PermissionController/res/values-fa/strings.xml
index 6a9a67315..ea7c66973 100644
--- a/PermissionController/res/values-fa/strings.xml
+++ b/PermissionController/res/values-fa/strings.xml
@@ -50,12 +50,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>
@@ -109,8 +109,8 @@
<!-- 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_only_foreground" msgid="7801170728159326195">"فقط هنگام استفاده از برنامه مجاز است"</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>
<string name="all_permissions" msgid="6911125611996872522">"همه اجازه‌ها"</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>
diff --git a/PermissionController/res/values-fi-v34/strings.xml b/PermissionController/res/values-fi-v34/strings.xml
index b2f95dc19..703a79ae2 100644
--- a/PermissionController/res/values-fi-v34/strings.xml
+++ b/PermissionController/res/values-fi-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Pääsy sijaintiin"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Sovellukset ja palvelut. Vaikka asetus olisi poissa päältä, mikrofonidataa saatetaan silti jakaa, kun soitat hätänumeroon"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Sovellukset ja palvelut"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-fr-rCA-v34/strings.xml b/PermissionController/res/values-fr-rCA-v34/strings.xml
index 347b04cc8..e4a7dc0c8 100644
--- a/PermissionController/res/values-fr-rCA-v34/strings.xml
+++ b/PermissionController/res/values-fr-rCA-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-fr-v34/strings.xml b/PermissionController/res/values-fr-v34/strings.xml
index f7f584b75..a320741dd 100644
--- a/PermissionController/res/values-fr-v34/strings.xml
+++ b/PermissionController/res/values-fr-v34/strings.xml
@@ -24,4 +24,10 @@
<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="location_settings_subtitle" msgid="6846532794702613851">"Pour les applis et services"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-gl-v34/strings.xml b/PermissionController/res/values-gl-v34/strings.xml
index cabf7a43a..ee0c721b7 100644
--- a/PermissionController/res/values-gl-v34/strings.xml
+++ b/PermissionController/res/values-gl-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acceso á localización"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para aplicacións e servizos. Aínda que esta opción de configuración se atope desactivada, poderán compartirse datos do micrófono se chamas a un número de emerxencias"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para aplicacións e servizos"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-gu-v34/strings.xml b/PermissionController/res/values-gu-v34/strings.xml
index ba8a5deb0..990a81509 100644
--- a/PermissionController/res/values-gu-v34/strings.xml
+++ b/PermissionController/res/values-gu-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"લોકેશન ઍક્સેસ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ઍપ અને સેવાઓ માટે. આ સેટિંગ બંધ હોવા છતાં પણ, જ્યારે તમે ઇમર્જન્સી નંબર પર કૉલ કરો ત્યારે હજુ પણ માઇક્રોફોનનો ડેટા શેર કરવામાં આવી શકે"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ઍપ અને સેવાઓ માટે"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-hi-v34/strings.xml b/PermissionController/res/values-hi-v34/strings.xml
index 7b95fb793..fb3460a9b 100644
--- a/PermissionController/res/values-hi-v34/strings.xml
+++ b/PermissionController/res/values-hi-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"जगह की जानकारी का ऐक्सेस"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ऐप्लिकेशन और सेवाओं के लिए. इस सेटिंग के बंद होने पर भी, माइक्रोफ़ोन के डेटा को शेयर किया जा सकता है. ऐसा तब होता है, जब किसी आपातकालीन नंबर पर कॉल किया जाता है"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ऐप्लिकेशन और सेवाओं के लिए"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml
index 1f334e4f3..d1b3e4048 100644
--- a/PermissionController/res/values-hi/strings.xml
+++ b/PermissionController/res/values-hi/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"नोट"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"डिफ़ॉल्ट वॉलेट ऐप्लिकेशन"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"वॉलेट ऐप्लिकेशन"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"वॉलेट ऐप्लिकेशन में, तरह-तरह के लेन-देन में इस्तेमाल की जाने वाली चीज़ों को स्टोर किया जा सकता है. जैसे, क्रेडिट कार्ड, लॉयल्टी कार्ड, कार के डिजिटल बटन वगैरह."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"वॉलेट ऐप्लिकेशन में, अलग-अलग तरह के लेन-देन में इस्तेमाल होने वाली चीज़ों को स्टोर किया जा सकता है. जैसे, क्रेडिट कार्ड, लॉयल्टी कार्ड, कार की डिजिटल कुंजी वगैरह."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"क्या <xliff:g id="APP_NAME">%1$s</xliff:g> को अपने डिफ़ॉल्ट वॉलेट ऐप्लिकेशन के तौर पर सेट करना है?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"अनुमति लेना ज़रूरी नहीं है"</string>
<string name="request_role_current_default" msgid="738722892438247184">"मौजूदा डिफ़ॉल्ट"</string>
diff --git a/PermissionController/res/values-hr-v34/strings.xml b/PermissionController/res/values-hr-v34/strings.xml
index 74a1d7d1e..e683f6a55 100644
--- a/PermissionController/res/values-hr-v34/strings.xml
+++ b/PermissionController/res/values-hr-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-hu-v34/strings.xml b/PermissionController/res/values-hu-v34/strings.xml
index 1a01b1cc0..ec3514c11 100644
--- a/PermissionController/res/values-hu-v34/strings.xml
+++ b/PermissionController/res/values-hu-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Helyhozzáférés"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Alkalmazásoknál és szolgáltatásoknál. Ha ki van kapcsolva ez a beállítás, segélyhívó szám hívásakor a rendszer továbbra is megoszthatja a mikrofonadatokat."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Alkalmazásoknál és szolgáltatásoknál"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-hy-v34/strings.xml b/PermissionController/res/values-hy-v34/strings.xml
index fb8997eb1..f09b46a7b 100644
--- a/PermissionController/res/values-hy-v34/strings.xml
+++ b/PermissionController/res/values-hy-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Տեղորոշման թույլտվություն"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Հավելվածների և ծառայությունների համար։ Եթե այս կարգավորումն անջատված է, խոսափողի տվյալները միևնույն է կարող են փոխանցվել, երբ զանգեք արտակարգ իրավիճակների որևէ հեռախոսահամարի"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Հավելվածների և ծառայությունների համար"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml
index 0d3f575ed..367f6f12c 100644
--- a/PermissionController/res/values-hy/strings.xml
+++ b/PermissionController/res/values-hy/strings.xml
@@ -403,7 +403,7 @@
<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="role_wallet_label" msgid="3719419175656204207">"Դրամապանակի կանխադրված հավելվ․"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Դրամապանակի կանխադրվ. հավելված"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Դրամապանակի հավելված"</string>
<string name="role_wallet_description" msgid="3726535836165949838">"Դրամապանակի հավելվածները կարող են պահել ձեր վարկային և մշտական հաճախորդի քարտերը, մեքենայի բանալիները և այլ բաներ, որոնք կհեշտացնեն ձեր գործարքները։"</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Նշե՞լ <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը որպես դրամապանակի կանխադրված հավելված"</string>
diff --git a/PermissionController/res/values-in-v34/strings.xml b/PermissionController/res/values-in-v34/strings.xml
index 7e0c0a609..5d0c4f56a 100644
--- a/PermissionController/res/values-in-v34/strings.xml
+++ b/PermissionController/res/values-in-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-is-v34/strings.xml b/PermissionController/res/values-is-v34/strings.xml
index b897bcc71..314b53efa 100644
--- a/PermissionController/res/values-is-v34/strings.xml
+++ b/PermissionController/res/values-is-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Aðgangur að staðsetningu"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"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="6846532794702613851">"Fyrir forrit og þjónustur"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-it-v34/strings.xml b/PermissionController/res/values-it-v34/strings.xml
index 27da7e634..70abec5c2 100644
--- a/PermissionController/res/values-it-v34/strings.xml
+++ b/PermissionController/res/values-it-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Accesso alla posizione"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Per app e servizi. Se questa impostazione viene disattivata, i dati del microfono potrebbero comunque essere condivisi quando chiami un numero di emergenza"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Per app e servizi"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-it/strings.xml b/PermissionController/res/values-it/strings.xml
index a8686ba8a..88ad07e81 100644
--- a/PermissionController/res/values-it/strings.xml
+++ b/PermissionController/res/values-it/strings.xml
@@ -403,10 +403,10 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"App per le note"</string>
<string name="role_notes_description" msgid="8496852798616883551">"App che ti permettono di prendere appunti sul tuo dispositivo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"note"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"App wallet predefinita"</string>
- <string name="role_wallet_short_label" msgid="6521288403762457452">"App wallet"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Le app wallet possono memorizzare carte di credito e fedeltà, chiavi della macchina e altro per facilitare varie forme di transazioni."</string>
- <string name="role_wallet_request_title" msgid="4770217108262737093">"Impostare <xliff:g id="APP_NAME">%1$s</xliff:g> come app wallet predefinita?"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"App portafoglio predefinita"</string>
+ <string name="role_wallet_short_label" msgid="6521288403762457452">"App portafoglio"</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Le app portafoglio possono memorizzare carte di credito e fedeltà, chiavi della macchina e altro per facilitare varie forme di transazioni."</string>
+ <string name="role_wallet_request_title" msgid="4770217108262737093">"Impostare <xliff:g id="APP_NAME">%1$s</xliff:g> come app portafoglio predefinita?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nessuna autorizzazione necessaria"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Valore predefinito attuale"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Non chiedermelo più"</string>
diff --git a/PermissionController/res/values-iw-v34/strings.xml b/PermissionController/res/values-iw-v34/strings.xml
index 370a20dcb..d2a5c12d3 100644
--- a/PermissionController/res/values-iw-v34/strings.xml
+++ b/PermissionController/res/values-iw-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"גישה למיקום"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"לאפליקציות ולשירותים. אם ההגדרה מושבתת, יכול להיות שנתוני המיקרופון ישותפו בכל זאת כשתתבצע שיחה למספר חירום"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"לאפליקציות ולשירותים"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ja-v34/strings.xml b/PermissionController/res/values-ja-v34/strings.xml
index 1a27a1df1..36120d0fc 100644
--- a/PermissionController/res/values-ja-v34/strings.xml
+++ b/PermissionController/res/values-ja-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"位置情報へのアクセス"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"アプリとサービスによるアクセス。この設定が OFF の場合でも、緊急通報番号に発信したときは、マイクのデータが共有されることがあります"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"アプリとサービスによるアクセス"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ka-v34/strings.xml b/PermissionController/res/values-ka-v34/strings.xml
index c3e4c7715..8f57c245b 100644
--- a/PermissionController/res/values-ka-v34/strings.xml
+++ b/PermissionController/res/values-ka-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"მდებარეობაზე წვდომა"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"აპებისა და სერვისებისთვის. მიკროფონის მონაცემები, შესაძლოა, მაინც გაზიარდეს გადაუდებელი დახმარების სამსახურის ნომერზე დარეკვისას, როცა ეს პარამეტრი გამორთულია"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"აპებისა და სერვისებისთვის"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-kk-v34/strings.xml b/PermissionController/res/values-kk-v34/strings.xml
index 002624b5a..7580e6ab6 100644
--- a/PermissionController/res/values-kk-v34/strings.xml
+++ b/PermissionController/res/values-kk-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Локацияны пайдалану рұқсаты"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Қолданбалар мен қызметтерге арналған. Бұл параметр өшірілсе де, құтқару қызметінің нөміріне қоңырау шалғанда, микрофон деректері жіберілуі мүмкін."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Қолданбалар мен қызметтерге арналған."</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-km-v34/strings.xml b/PermissionController/res/values-km-v34/strings.xml
index ccf92d186..cb0f46c17 100644
--- a/PermissionController/res/values-km-v34/strings.xml
+++ b/PermissionController/res/values-km-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ការចូលប្រើប្រាស់ទីតាំង"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"សម្រាប់កម្មវិធី និងសេវាកម្ម។ ប្រសិនបើការកំណត់នេះ​ត្រូវ​បាន​បិទ ទិន្នន័យមីក្រូហ្វូននៅតែអាចត្រូវបានចែករំលែកដដែល នៅពេលអ្នកហៅទៅលេខសង្គ្រោះបន្ទាន់"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"សម្រាប់កម្មវិធី និងសេវាកម្ម"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-kn-v34/strings.xml b/PermissionController/res/values-kn-v34/strings.xml
index 34a939459..6e0ee5f75 100644
--- a/PermissionController/res/values-kn-v34/strings.xml
+++ b/PermissionController/res/values-kn-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ಸ್ಥಳದ ಆ್ಯಕ್ಸೆಸ್"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸೇವೆಗಳಿಗಾಗಿ. ಈ ಸೆಟ್ಟಿಂಗ್ ಆಫ್ ಆಗಿದ್ದಾಗಲೂ, ನೀವು ತುರ್ತು ಸಂಖ್ಯೆಯೊಂದಕ್ಕೆ ಕರೆ ಮಾಡಿದಾಗ ಮೈಕ್ರೊಫೋನ್ ಡೇಟಾವನ್ನು ಹಂಚಿಕೊಳ್ಳಬಹುದು"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸೇವೆಗಳಿಗಾಗಿ"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-kn/strings.xml b/PermissionController/res/values-kn/strings.xml
index 262f9dca2..102e77dd5 100644
--- a/PermissionController/res/values-kn/strings.xml
+++ b/PermissionController/res/values-kn/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"ಟಿಪ್ಪಣಿಗಳು"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"ಡೀಫಾಲ್ಟ್ ವಾಲೆಟ್ ಆ್ಯಪ್"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Wallet ಆ್ಯಪ್"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Wallet ಆ್ಯಪ್‌ಗಳು ನಿಮ್ಮ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಲಾಯಲ್ಟಿ ಕಾರ್ಡ್‌ಗಳು, ಕಾರ್ ಕೀಗಳು ಮತ್ತು ವಿವಿಧ ವಹಿವಾಟುಗಳಿಗೆ ಸಹಾಯ ಮಾಡುವ ಇತರ ವಿಷಯಗಳನ್ನು ಸಂಗ್ರಹಿಸಬಹುದು."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"ವಾಲೆಟ್ ಆ್ಯಪ್‌ಗಳು ನಿಮ್ಮ ಕ್ರೆಡಿಟ್ ಮತ್ತು ಲಾಯಲ್ಟಿ ಕಾರ್ಡ್‌ಗಳು, ಕಾರ್ ಕೀಗಳು ಮತ್ತು ವಿವಿಧ ವಹಿವಾಟುಗಳಿಗೆ ಸಹಾಯ ಮಾಡುವ ಇತರ ವಿಷಯಗಳನ್ನು ಸಂಗ್ರಹಿಸಬಹುದು."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್ ಅನ್ನು ನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ವಾಲೆಟ್ ಆ್ಯಪ್ ಆಗಿ ಸೆಟ್ ಮಾಡಬೇಕೆ?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"ಯಾವುದೇ ಅನುಮತಿಗಳ ಅಗತ್ಯವಿಲ್ಲ"</string>
<string name="request_role_current_default" msgid="738722892438247184">"ಪ್ರಸ್ತುತ ಡೀಫಾಲ್ಟ್"</string>
diff --git a/PermissionController/res/values-ko-v34/strings.xml b/PermissionController/res/values-ko-v34/strings.xml
index 7b3091170..17b857526 100644
--- a/PermissionController/res/values-ko-v34/strings.xml
+++ b/PermissionController/res/values-ko-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"위치 정보 액세스"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"앱 및 서비스에 적용됩니다. 설정이 꺼져 있어도 긴급 전화번호로 전화를 걸 때 마이크 데이터가 계속 공유될 수 있습니다."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"앱 및 서비스에 적용"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ky-v34/strings.xml b/PermissionController/res/values-ky-v34/strings.xml
index 15fc8424e..d6f9a46fc 100644
--- a/PermissionController/res/values-ky-v34/strings.xml
+++ b/PermissionController/res/values-ky-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Жайгашкан жерди көрсөтүү"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Колдонмолор жана кызматтар үчүн. Бул параметр өчүп турса да, кырсыктаганда жардамга келчү кызматтын номерине чалганыңызда микрофондогу нерселер өткөрүлүшү мүмкүн."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Колдонмолор жана кызматтар үчүн"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ky/strings.xml b/PermissionController/res/values-ky/strings.xml
index 739c14744..068a1a283 100644
--- a/PermissionController/res/values-ky/strings.xml
+++ b/PermissionController/res/values-ky/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"кыска жазуулар"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Демейки капчык колдонмосу"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Капчык колдонмосу"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Капчык колдонмолору ар кандай транзакция формаларында жардам берүү үчүн насыя жана туруктуу кардардын карталарын, унаа ачкычтарын жана башка нерселерди сактай алат."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Капчык колдонмосунда насыя жана туруктуу кардардын карталары, унаанын ачкычтары сыяктуу санарип нерселер сакталат. Алардын жардамы менен ар кандай транзакцияларды аткара аласыз."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"<xliff:g id="APP_NAME">%1$s</xliff:g> демейки капчык колдонмоңуз катары тууралансынбы?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Уруксаттардын кереги жок"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Учурдагы демейки колдонмо"</string>
diff --git a/PermissionController/res/values-lo-v34/strings.xml b/PermissionController/res/values-lo-v34/strings.xml
index 431b80ec1..b2f97825a 100644
--- a/PermissionController/res/values-lo-v34/strings.xml
+++ b/PermissionController/res/values-lo-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ສິດເຂົ້າເຖິງສະຖານທີ່"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ສຳລັບແອັບ ແລະ ບໍລິການຕ່າງໆ. ຫາກປິດການຕັ້ງຄ່ານີ້ໄວ້, ຂໍ້ມູນໄມໂຄຣໂຟນອາດຍັງຖືກແບ່ງປັນເມື່ອທ່ານໂທຫາເບີໂທສຸກເສີນ"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ສຳລັບແອັບ ແລະ ບໍລິການຕ່າງໆ"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-lt-v34/strings.xml b/PermissionController/res/values-lt-v34/strings.xml
index f7a60d198..9667cc3bb 100644
--- a/PermissionController/res/values-lt-v34/strings.xml
+++ b/PermissionController/res/values-lt-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Prieiga prie vietovės"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Programos ir paslaugos. Jei šis nustatymas išjungtas, mikrofono duomenys vis tiek gali būti bendrinami, skambinant pagalbos numeriu"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Programos ir paslaugos"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-lv-v34/strings.xml b/PermissionController/res/values-lv-v34/strings.xml
index 3c99e3275..f4b447480 100644
--- a/PermissionController/res/values-lv-v34/strings.xml
+++ b/PermissionController/res/values-lv-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Piekļuve atrašanās vietai"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Lietotnēm un pakalpojumiem. Ja šis iestatījums ir izslēgts, mikrofona dati joprojām var tikt kopīgoti, kad zvanīsiet uz ārkārtas numuru."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Lietotnēm un pakalpojumiem"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-mk-v34/strings.xml b/PermissionController/res/values-mk-v34/strings.xml
index e8f9afc25..d955a5fa8 100644
--- a/PermissionController/res/values-mk-v34/strings.xml
+++ b/PermissionController/res/values-mk-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Пристап до локацијата"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"За апликации и услуги. Ако поставкава е исклучена, податоците од микрофонот може сепак да се споделат кога ќе се јавите на број за итни случаи"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"За апликации и услуги"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index 21218f1cc..9cc275b88 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -403,9 +403,9 @@
<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="role_wallet_label" msgid="3719419175656204207">"Стандардна аплик. за Wallet"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Стандардна аплик. за паричник"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Апликација за Wallet"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Апликациите Wallet може да ги складираат кредитните и картичките за лојалност, клучевите за автомобилот, како и други работи за олеснување на различните форми на трансакции."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Апликациите за паричник може да ги складираат кредитните и картичките за лојалност, клучевите за автомобилот, како и други работи за олеснување на различните форми на трансакции."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Да се постави <xliff:g id="APP_NAME">%1$s</xliff:g> како стандардна апликација за Wallet?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Не се потребни дозволи"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Стандардна апликација сега"</string>
diff --git a/PermissionController/res/values-ml-v34/strings.xml b/PermissionController/res/values-ml-v34/strings.xml
index 7f22bbf9c..636b605ed 100644
--- a/PermissionController/res/values-ml-v34/strings.xml
+++ b/PermissionController/res/values-ml-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ലൊക്കേഷൻ ആക്‌സസ്"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ആപ്പുകൾക്കും സേവനങ്ങൾക്കും. ഈ ക്രമീകരണം ഓഫാണെങ്കിൽ, നിങ്ങൾ അടിയന്തര നമ്പറിൽ വിളിക്കുമ്പോഴും മൈക്രോഫോൺ ഡാറ്റ തുടർന്നും പങ്കിട്ടേക്കാം"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ആപ്പുകൾക്കും സേവനങ്ങൾക്കും"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-mn-v34/strings.xml b/PermissionController/res/values-mn-v34/strings.xml
index fc5ac1818..96c011d52 100644
--- a/PermissionController/res/values-mn-v34/strings.xml
+++ b/PermissionController/res/values-mn-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Байршлын хандалт"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Апп болон үйлчилгээнүүдэд. Энэ тохиргоо унтраалттай тохиолдолд таныг яаралтай тусламжийн утасны дугаар луу залгах үед микрофоны өгөгдлийг хуваалцсан хэвээр байж магадгүй"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Апп болон үйлчилгээнүүдэд"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml
index dae627b70..6c37d0e96 100644
--- a/PermissionController/res/values-mn/strings.xml
+++ b/PermissionController/res/values-mn/strings.xml
@@ -28,7 +28,7 @@
<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_and_dont_ask_again" msgid="1748925431574312595">"Бүү зөвшөөрч, дахин битгий асуу"</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>
@@ -45,7 +45,7 @@
<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>
+ <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>
<string name="permission_revoked_none" msgid="9213345075484381180">"алийг нь ч цуцлаагүй"</string>
diff --git a/PermissionController/res/values-mr-v34/strings.xml b/PermissionController/res/values-mr-v34/strings.xml
index 8c9152379..991d880e3 100644
--- a/PermissionController/res/values-mr-v34/strings.xml
+++ b/PermissionController/res/values-mr-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"स्थान अ‍ॅक्सेस"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ॲप्स आणि सेवांसाठी. हे सेटिंग बंद असल्यास, तुम्ही आणीबाणी नंबरवर कॉल करता, तेव्हा मायक्रोफोन डेटा तरीही शेअर केला जाऊ शकतो"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ॲप्स आणि सेवांसाठी"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-mr/strings.xml b/PermissionController/res/values-mr/strings.xml
index d7a25e0e3..b81ff6c88 100644
--- a/PermissionController/res/values-mr/strings.xml
+++ b/PermissionController/res/values-mr/strings.xml
@@ -586,7 +586,7 @@
<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_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>
<string name="media_confirm_dialog_title_a_to_p_aural_deny" msgid="7841428716317307685">"इतर फाइलच्या अ‍ॅक्सेसलादेखील अनुमती दिली जाणार नाही"</string>
diff --git a/PermissionController/res/values-ms-v34/strings.xml b/PermissionController/res/values-ms-v34/strings.xml
index 6fd21c7af..2032994c3 100644
--- a/PermissionController/res/values-ms-v34/strings.xml
+++ b/PermissionController/res/values-ms-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Akses lokasi"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Untuk apl dan perkhidmatan. Jika tetapan ini dimatikan, data mikrofon mungkin masih dikongsi apabila anda memanggil nombor kecemasan"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Untuk apl dan perkhidmatan"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-my-v34/strings.xml b/PermissionController/res/values-my-v34/strings.xml
index 4d4e03401..27ac5bae8 100644
--- a/PermissionController/res/values-my-v34/strings.xml
+++ b/PermissionController/res/values-my-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"တည်နေရာသုံးခွင့်"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"အက်ပ်နှင့် ဝန်ဆောင်မှုများအတွက်။ ဤဆက်တင်ကို ပိတ်ထားသော်လည်း အရေးပေါ် နံပါတ်ကို သင်ခေါ်ဆိုချိန်တွင် မိုက်ခရိုဖုန်းဒေတာ မျှဝေနိုင်သေးသည်"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"အက်ပ်နှင့် ဝန်ဆောင်မှုများအတွက်"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml
index 6188e6b23..064a58993 100644
--- a/PermissionController/res/values-my/strings.xml
+++ b/PermissionController/res/values-my/strings.xml
@@ -349,8 +349,8 @@
<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">"မူလဒစ်ဂျစ်တယ် Assistant အက်ပ်"</string>
- <string name="role_assistant_short_label" msgid="3369003713187703399">"ဒစ်ဂျစ်တယ် Assistant အက်ပ်"</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_browser_label" msgid="2877796144554070207">"မူရင်း ဘရောင်ဇာအက်ပ်"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"ဘရောင်ဇာ အက်ပ်"</string>
diff --git a/PermissionController/res/values-nb-v34/strings.xml b/PermissionController/res/values-nb-v34/strings.xml
index a7bb456d5..ea67fbd89 100644
--- a/PermissionController/res/values-nb-v34/strings.xml
+++ b/PermissionController/res/values-nb-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Posisjonstilgang"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"For apper og tjenester. Hvis denne innstillingen er av, kan mikrofondata fremdeles deles når du ringer et nødnummer"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"For apper og tjenester"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ne-v34/strings.xml b/PermissionController/res/values-ne-v34/strings.xml
index 421c5a8e0..c7930c109 100644
--- a/PermissionController/res/values-ne-v34/strings.xml
+++ b/PermissionController/res/values-ne-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"लोकेसन एक्सेस"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"एप तथा सेवाहरूका हकमा। यो सेटिङ अफ गरिएको अवस्थामा तपाईंले आपत्‍कालीन नम्बरमा कल गर्नुभयो भने माइक्रोफोनसम्बन्धी जानकारी अझै पनि सेयर गरिन सक्छ"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"एप तथा सेवाहरूका हकमा"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index 1bb9083ce..374d98ddc 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"नोटहरू"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"डिफल्ट Wallet एप"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Wallet एप"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"तपाईंलाई विभिन्न तरिकाले कारोबारहरू गर्न सघाउन Wallet एपमा तपाईंका क्रेडिट कार्ड तथा लोयल्टी कार्ड, कार कीलगायतका अन्य कुराहरू भण्डारण गर्न सकिन्छ।"</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"तपाईंलाई विभिन्न तरिकाले कारोबार गर्न सघाउन Wallet एपमा तपाईंका क्रेडिट कार्ड तथा लोयल्टी कार्ड, कार कीलगायतका कुराहरू पनि भण्डारण गर्न सकिन्छ।"</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"<xliff:g id="APP_NAME">%1$s</xliff:g> लाई आफ्नो डिफल्ट Wallet एपका रूपमा सेट गर्ने हो?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"कुनै पनि अनुमति चाहिन्न"</string>
<string name="request_role_current_default" msgid="738722892438247184">"हालको डिफल्ट एप"</string>
@@ -434,7 +434,7 @@
<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_system_default" msgid="6218386768175513760">"(डिफल्ट सिस्टम एप)"</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>
<string name="car_default_app_selected_with_info" msgid="1932204186080593500">"चयन गरिएको - <xliff:g id="ADDITIONAL_INFO">%1$s</xliff:g>"</string>
diff --git a/PermissionController/res/values-nl-v34/strings.xml b/PermissionController/res/values-nl-v34/strings.xml
index b3265d254..77cb85341 100644
--- a/PermissionController/res/values-nl-v34/strings.xml
+++ b/PermissionController/res/values-nl-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-or-v34/strings.xml b/PermissionController/res/values-or-v34/strings.xml
index 2994a3f25..30b8eefb6 100644
--- a/PermissionController/res/values-or-v34/strings.xml
+++ b/PermissionController/res/values-or-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ଲୋକେସନ ଆକ୍ସେସ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ। ଯଦି ଏହି ସେଟିଂ ବନ୍ଦ ଥାଏ, ତେବେ ଆପଣ ଏକ ଜରୁରୀକାଳୀନ ନମ୍ବରକୁ କଲ କରିବା ସମୟରେ ମାଇକ୍ରୋଫୋନ ଡାଟା ଏବେ ବି ସେୟାର କରାଯାଇପାରେ"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ଆପ୍ସ ଏବଂ ସେବାଗୁଡ଼ିକ ପାଇଁ"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pa-v34/strings.xml b/PermissionController/res/values-pa-v34/strings.xml
index c0b70fb57..9c9f2ff69 100644
--- a/PermissionController/res/values-pa-v34/strings.xml
+++ b/PermissionController/res/values-pa-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ਟਿਕਾਣਾ ਪਹੁੰਚ"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ। ਇਸ ਸੈਟਿੰਗ ਦੇ ਬੰਦ ਹੋਣ \'ਤੇ, ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਐਮਰਜੈਂਸੀ ਨੰਬਰ \'ਤੇ ਕਾਲ ਕਰਦੇ ਹੋ ਤਾਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਡਾਟੇ ਨੂੰ ਫਿਰ ਵੀ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਲਈ"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pl-v34/strings.xml b/PermissionController/res/values-pl-v34/strings.xml
index b69bf4c4f..936010b07 100644
--- a/PermissionController/res/values-pl-v34/strings.xml
+++ b/PermissionController/res/values-pl-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Dostęp do lokalizacji"</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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index 95759a247..8def9038b 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notatki"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Domyślna aplikacja portfela"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Aplikacja portfela cyfrowego"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Aplikacje portfeli cyfrowych mogą przechowywać karty kredytowe i lojalnościowe, kluczyki do samochodu i inne rzeczy, aby pomóc w różnych formach transakcji."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Aby ułatwić sobie wykonywanie różny form transakcji, w aplikacjach portfeli cyfrowych można przechowywać karty kredytowe i lojalnościowe, kluczyki do samochodu i inne rzeczy."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Ustawić aplikację <xliff:g id="APP_NAME">%1$s</xliff:g> jako domyślną aplikację portfela cyfrowego?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nie potrzebuje uprawnień"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Bieżąca aplikacja domyślna"</string>
diff --git a/PermissionController/res/values-pt-rBR-v34/strings.xml b/PermissionController/res/values-pt-rBR-v34/strings.xml
index 6e77e0432..1a2003a65 100644
--- a/PermissionController/res/values-pt-rBR-v34/strings.xml
+++ b/PermissionController/res/values-pt-rBR-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acesso ao local"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para apps e serviços. Se esta configuração estiver desativada, os dados do microfone ainda poderão ser compartilhados quando você ligar para um número de emergência"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para apps e serviços"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pt-rBR/strings.xml b/PermissionController/res/values-pt-rBR/strings.xml
index aeeb6f4bf..036adb6a4 100644
--- a/PermissionController/res/values-pt-rBR/strings.xml
+++ b/PermissionController/res/values-pt-rBR/strings.xml
@@ -403,9 +403,9 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"App de notas"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Apps que permitem a criação de notas no dispositivo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notas"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"App de carteira padrão"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Carteira digital padrão"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"App de carteira"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Os apps de carteira podem armazenar seus cartões de crédito e fidelidade, chaves do carro e outras coisas para ajudar em diversas formas de transações."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Os apps de carteira digital armazenam seus cartões de crédito e de fidelidade,as chaves do carro, entre outros itens, para agilizar suas transações."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Definir <xliff:g id="APP_NAME">%1$s</xliff:g> como seu app de carteira padrão?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nenhuma permissão necessária"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Padrão atual"</string>
diff --git a/PermissionController/res/values-pt-rPT-v34/strings.xml b/PermissionController/res/values-pt-rPT-v34/strings.xml
index 2f7ce1be2..2b663e883 100644
--- a/PermissionController/res/values-pt-rPT-v34/strings.xml
+++ b/PermissionController/res/values-pt-rPT-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acesso à localização"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para apps e serviços. Se esta definição estiver desativada, os dados do microfone ainda podem ser partilhados quando ligar para um número de emergência"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para apps e serviços"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pt-v34/strings.xml b/PermissionController/res/values-pt-v34/strings.xml
index 6e77e0432..1a2003a65 100644
--- a/PermissionController/res/values-pt-v34/strings.xml
+++ b/PermissionController/res/values-pt-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Acesso ao local"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para apps e serviços. Se esta configuração estiver desativada, os dados do microfone ainda poderão ser compartilhados quando você ligar para um número de emergência"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para apps e serviços"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-pt/strings.xml b/PermissionController/res/values-pt/strings.xml
index aeeb6f4bf..036adb6a4 100644
--- a/PermissionController/res/values-pt/strings.xml
+++ b/PermissionController/res/values-pt/strings.xml
@@ -403,9 +403,9 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"App de notas"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Apps que permitem a criação de notas no dispositivo"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"notas"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"App de carteira padrão"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Carteira digital padrão"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"App de carteira"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Os apps de carteira podem armazenar seus cartões de crédito e fidelidade, chaves do carro e outras coisas para ajudar em diversas formas de transações."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Os apps de carteira digital armazenam seus cartões de crédito e de fidelidade,as chaves do carro, entre outros itens, para agilizar suas transações."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Definir <xliff:g id="APP_NAME">%1$s</xliff:g> como seu app de carteira padrão?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Nenhuma permissão necessária"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Padrão atual"</string>
diff --git a/PermissionController/res/values-ro-v34/strings.xml b/PermissionController/res/values-ro-v34/strings.xml
index e57e8c91a..18a8cb8c6 100644
--- a/PermissionController/res/values-ro-v34/strings.xml
+++ b/PermissionController/res/values-ro-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Accesul la locație"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Pentru aplicații și servicii. Chiar dacă setarea este dezactivată, datele de la microfon pot fi trimise când apelezi un număr de urgență."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Pentru aplicații și servicii"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ru-v34/strings.xml b/PermissionController/res/values-ru-v34/strings.xml
index 64a927b69..df75a96f9 100644
--- a/PermissionController/res/values-ru-v34/strings.xml
+++ b/PermissionController/res/values-ru-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Доступ к геоданным"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Для приложений и сервисов. Даже если эта функция отключена, данные микрофона могут передаваться при звонке на номер экстренной службы."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Для приложений и сервисов"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-si-v34/strings.xml b/PermissionController/res/values-si-v34/strings.xml
index 26121467a..db6524d77 100644
--- a/PermissionController/res/values-si-v34/strings.xml
+++ b/PermissionController/res/values-si-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"ස්ථාන ප්‍රවේශය"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"යෙදුම් සහ සේවා සඳහා. මෙම සැකසීම ක්‍රියාවිරහිත නම්, ඔබ හදිසි ඇමතුම් අංකයක් අමතන විට මයික්‍රෆෝනයේ දත්ත තවම බෙදා ගත හැක."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"යෙදුම් සහ සේවා සඳහා"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sk-v34/strings.xml b/PermissionController/res/values-sk-v34/strings.xml
index 5f84f5059..759f8b1d0 100644
--- a/PermissionController/res/values-sk-v34/strings.xml
+++ b/PermissionController/res/values-sk-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Prístup k polohe"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"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="6846532794702613851">"Pre aplikácie a služby"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sl-v34/strings.xml b/PermissionController/res/values-sl-v34/strings.xml
index 18afff3d1..3834a8bbe 100644
--- a/PermissionController/res/values-sl-v34/strings.xml
+++ b/PermissionController/res/values-sl-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sq-v34/strings.xml b/PermissionController/res/values-sq-v34/strings.xml
index bf9c922cd..4fe34fd1e 100644
--- a/PermissionController/res/values-sq-v34/strings.xml
+++ b/PermissionController/res/values-sq-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Qasja te vendndodhja"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Për aplikacionet dhe shërbimet. Nëse ky cilësim është joaktiv, të dhënat e mikrofonit mund të vazhdojnë të ndahen kur telefonon një numër urgjence."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Për aplikacionet dhe shërbimet"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sr-v34/strings.xml b/PermissionController/res/values-sr-v34/strings.xml
index 89233996c..b0fa30b98 100644
--- a/PermissionController/res/values-sr-v34/strings.xml
+++ b/PermissionController/res/values-sr-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Приступ локацији"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"За апликације и услуге. Ако је ово подешавање искључено, подаци микрофона могу и даље да се деле када позовете број за хитне случајеве"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"За апликације и услуге"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml
index 4f69c0bbd..80a4d3121 100644
--- a/PermissionController/res/values-sr/strings.xml
+++ b/PermissionController/res/values-sr/strings.xml
@@ -405,7 +405,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"белешке"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Подразумевана апликација Новчаник"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Апликација Новчаник"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Апликације Новчаник могу да чувају ваше кредитне картице и картице лојалности, кључеве од аутомобила и друге ствари како би вам помогли у различитим облицима трансакција."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Апликације Новчаник могу да чувају ваше кредитне картице и картице лојалности, кључеве од аутомобила и друге ствари како би вам помогли при различитим трансакцијама."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Желите да подесите <xliff:g id="APP_NAME">%1$s</xliff:g> као подразумевану апликацију Новчаник?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Није потребна ниједна дозвола"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Тренутно подразумевана"</string>
diff --git a/PermissionController/res/values-sv-v34/strings.xml b/PermissionController/res/values-sv-v34/strings.xml
index 09e204e2e..626da31b9 100644
--- a/PermissionController/res/values-sv-v34/strings.xml
+++ b/PermissionController/res/values-sv-v34/strings.xml
@@ -24,4 +24,10 @@
<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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-sw-v34/strings.xml b/PermissionController/res/values-sw-v34/strings.xml
index 52a1c7ceb..841b031f6 100644
--- a/PermissionController/res/values-sw-v34/strings.xml
+++ b/PermissionController/res/values-sw-v34/strings.xml
@@ -24,4 +24,10 @@
<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, data ya maikrofoni bado inaweza ikashirikiwa unapopiga namba ya dharura"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Kwenye programu na huduma"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ta-v34/strings.xml b/PermissionController/res/values-ta-v34/strings.xml
index b92b9a184..a26f1f838 100644
--- a/PermissionController/res/values-ta-v34/strings.xml
+++ b/PermissionController/res/values-ta-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"இருப்பிட அணுகல்"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ஆப்ஸ் மற்றும் சேவைகளுக்கு. இந்த அமைப்பு முடக்கப்பட்டிருந்தாலும் அவசர உதவி எண்ணை நீங்கள் அழைக்கும்போது மைக்ரோஃபோன் தரவு பகிரப்படலாம்"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ஆப்ஸ் &amp; சேவைகளுக்கு"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-te-v34/strings.xml b/PermissionController/res/values-te-v34/strings.xml
index c8281ea1d..a8ba9b116 100644
--- a/PermissionController/res/values-te-v34/strings.xml
+++ b/PermissionController/res/values-te-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"లొకేషన్ యాక్సెస్"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"యాప్‌లు, సర్వీస్‌ల కోసం. ఈ సెట్టింగ్ ఆఫ్ చేసి ఉన్నా కూడా, మీరు ఎమర్జెన్సీ నంబర్‌కు కాల్ చేసినప్పుడు మైక్రోఫోన్ డేటా షేర్ చేయబడవచ్చు"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"యాప్‌లు, సర్వీస్‌ల కోసం"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-th-v34/strings.xml b/PermissionController/res/values-th-v34/strings.xml
index 8e6bae837..34f726b30 100644
--- a/PermissionController/res/values-th-v34/strings.xml
+++ b/PermissionController/res/values-th-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"สิทธิ์เข้าถึงตำแหน่ง"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"สำหรับแอปและบริการ หากปิดการตั้งค่านี้ ระบบอาจยังคงแชร์ข้อมูลไมโครโฟนเมื่อคุณโทรหาหมายเลขฉุกเฉิน"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"สำหรับแอปและบริการ"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-tl-v34/strings.xml b/PermissionController/res/values-tl-v34/strings.xml
index 4ed588f80..7326d6f7a 100644
--- a/PermissionController/res/values-tl-v34/strings.xml
+++ b/PermissionController/res/values-tl-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Access sa lokasyon"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Para sa mga app at serbisyo. Kung naka-off ang setting na ito, posible pa ring ibahagi ang data ng mikropono kapag tumawag ka sa isang pang-emergency na numero"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Para sa mga app at serbisyo"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-tr-v34/strings.xml b/PermissionController/res/values-tr-v34/strings.xml
index 81d533562..7cbdefec6 100644
--- a/PermissionController/res/values-tr-v34/strings.xml
+++ b/PermissionController/res/values-tr-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Konum erişimi"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Uygulamalar ve hizmetler için. Bu ayar kapalıyken bir acil durum numarasını aradığınızda mikrofon verileri paylaşılmaya devam edebilir."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Uygulamalar ve hizmetler için"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-uk-v34/strings.xml b/PermissionController/res/values-uk-v34/strings.xml
index 5d14c8ebe..7b3902303 100644
--- a/PermissionController/res/values-uk-v34/strings.xml
+++ b/PermissionController/res/values-uk-v34/strings.xml
@@ -17,11 +17,17 @@
<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>
<string name="location_settings" msgid="8863940440881290182">"Доступ до геоданих"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Для додатків і сервісів. Якщо це налаштування вимкнено, дані мікрофона можуть усе одно передаватися під час виклику екстреного номера."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Для додатків і сервісів"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-ur-v34/strings.xml b/PermissionController/res/values-ur-v34/strings.xml
index 37b5ec635..56e61c37b 100644
--- a/PermissionController/res/values-ur-v34/strings.xml
+++ b/PermissionController/res/values-ur-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"مقام تک رسائی"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"ایپس اور سروسز کے لیے۔ اگر یہ ترتیب آف ہو تو آپ کے ایمرجنسی نمبر پر کال کرتے وقت بھی مائیکروفون کے ڈیٹا کا اشتراک کیا جا سکتا ہے"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"ایپس اور سروسز کے لیے"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-uz-v34/strings.xml b/PermissionController/res/values-uz-v34/strings.xml
index 3c48cd9d1..5e5a48cf8 100644
--- a/PermissionController/res/values-uz-v34/strings.xml
+++ b/PermissionController/res/values-uz-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Joylashuv axborotiga ruxsat"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Ilovalar va xizmatlar uchun. Bu sozlama yoqilmasa, favqulodda xizmat raqamiga telefon qilganingizda mikrofon maʼlumotlari hamon ulashilishi mumkin"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Ilovalar va xizmatlar uchun"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-uz/strings.xml b/PermissionController/res/values-uz/strings.xml
index 3ef292d47..01c1cab12 100644
--- a/PermissionController/res/values-uz/strings.xml
+++ b/PermissionController/res/values-uz/strings.xml
@@ -403,10 +403,10 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"Qaydlar ilovasi"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Qurilmangizda qaydlar olish imkonini beruvchi ilovalar"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"qaydlar"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"Standart hamyon ilovasi"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Birlamchi hamyon ilovasi"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Hamyon ilovasi"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Hamyon ilovasi kredit, sodiqlik va avtomobil kalitlari hamda boshqa raqamli mahsulotlarni saqlashi mumkin. Bu har xil turdagi operatsiyalarni amalga oshirishni yanada qulaylashtiradi."</string>
- <string name="role_wallet_request_title" msgid="4770217108262737093">"<xliff:g id="APP_NAME">%1$s</xliff:g> standart hamyon ilovasi sifatida sozlansinmi?"</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Hamyon ilovalarda kredit va sodiqlik kartalari, avtomobil kalitlari hamda boshqa raqamli mahsulotlarni saqlash mumkin. Bu har xil turdagi amaliyotlarni bajarishni yanada qulaylashtiradi."</string>
+ <string name="role_wallet_request_title" msgid="4770217108262737093">"<xliff:g id="APP_NAME">%1$s</xliff:g> birlamchi hamyon ilovasi sifatida belgilansinmi?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Hech qanday ruxsat zarur emas"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Hozirda asosiy ilova"</string>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Boshqa soʻralmasin"</string>
diff --git a/PermissionController/res/values-v34/dimens.xml b/PermissionController/res/values-v34/dimens.xml
index 2e8b50fd0..a0eff1154 100644
--- a/PermissionController/res/values-v34/dimens.xml
+++ b/PermissionController/res/values-v34/dimens.xml
@@ -22,4 +22,11 @@
<dimen name="sc_button_corner_radius_small">4dp</dimen>
<dimen name="sc_brand_chip_corner_radius">20dp</dimen>
<dimen name="sc_brand_chip_padding">6dp</dimen>
+
+ <!-- START ENHANCED CONFIRMATION DIALOG -->
+ <dimen name="enhanced_confirmation_dialog_padding">24dp</dimen>
+ <dimen name="enhanced_confirmation_dialog_padding_bottom">32dp</dimen>
+ <dimen name="enhanced_confirmation_dialog_title_bottom_padding">16dp</dimen>
+ <dimen name="enhanced_confirmation_dialog_icon_size">32dp</dimen>
+ <!-- END ENHANCED CONFIRMATION DIALOG -->
</resources> \ No newline at end of file
diff --git a/PermissionController/res/values-v34/strings.xml b/PermissionController/res/values-v34/strings.xml
index 26a9b4bcc..32ac5b4d0 100644
--- a/PermissionController/res/values-v34/strings.xml
+++ b/PermissionController/res/values-v34/strings.xml
@@ -32,4 +32,17 @@
<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>
+
+ <!-- START ENHANCED CONFIRMATION DIALOG -->
+
+ <!--Title for dialog displayed to tell user that settings are blocked by setting restrictions [CHAR LIMIT=50] -->
+ <string name="enhanced_confirmation_dialog_title">Restricted setting</string>
+ <!--Content for dialog displayed to tell user that settings are blocked by setting restrictions [CHAR LIMIT=100] -->
+ <string name="enhanced_confirmation_dialog_desc">For your security, this setting is currently unavailable.</string>
+ <!-- Button label to allow the user to view additional information [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=2416766240581561009] -->
+ <string name="enhanced_confirmation_dialog_learn_more">Learn more</string>
+ <!-- Help URI, action disabled by restricted settings [DO NOT TRANSLATE] -->
+ <string name="help_url_action_disabled_by_restricted_settings" translatable="false"></string>
+
+ <!-- END ENHANCED CONFIRMATION DIALOG -->
</resources>
diff --git a/PermissionController/res/values-v34/styles.xml b/PermissionController/res/values-v34/styles.xml
index 53780ce76..9548acb5b 100644
--- a/PermissionController/res/values-v34/styles.xml
+++ b/PermissionController/res/values-v34/styles.xml
@@ -371,4 +371,15 @@
<!-- END SAFETY CENTER SUBPAGE -->
+ <!-- START ENHANCED CONFIRMATION DIALOG -->
+
+ <style name="TextAppearance.EnhancedConfirmationDialogHeadline"
+ parent="@android:style/TextAppearance.DeviceDefault.Headline">
+ </style>
+
+ <style name="TextAppearance.EnhancedConfirmationDialogMessage"
+ parent="@android:style/TextAppearance.DeviceDefault">
+ </style>
+
+ <!-- END ENHANCED CONFIRMATION DIALOG -->
</resources> \ No newline at end of file
diff --git a/PermissionController/res/values-vi-v34/strings.xml b/PermissionController/res/values-vi-v34/strings.xml
index 618a266d8..ef2651d8d 100644
--- a/PermissionController/res/values-vi-v34/strings.xml
+++ b/PermissionController/res/values-vi-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Quyền truy cập thông tin vị trí"</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>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-watch/strings.xml b/PermissionController/res/values-watch/strings.xml
index f940eae65..60aca8fe9 100644
--- a/PermissionController/res/values-watch/strings.xml
+++ b/PermissionController/res/values-watch/strings.xml
@@ -35,4 +35,25 @@
<!-- Generic text to indicate Cancel. [CHAR LIMIT=10] -->
<string name="generic_cancel">Cancel</string>
+
+ <!-- [CHAR LIMIT=25] App can always (when app is in foreground or background) access the resource protected by the permission -->
+ <string name="permission_access_always">All the time</string>
+
+ <!-- App can only access the resource protected by the permission while app is in foreground [CHAR LIMIT=25]-->
+ <string name="permission_access_only_foreground">While using app</string>
+
+ <!-- Title for the dialog button to allow a permission grant when you can also only allow in the foreground. [CHAR LIMIT=25] -->
+ <string name="app_permission_button_allow_always">All the time</string>
+
+ <!-- Title for the dialog button to allow a permission grant only when the app is in the foreground. [CHAR LIMIT=25] -->
+ <string name="app_permission_button_allow_foreground">While using app</string>
+
+ <!-- Title for the dialog button to allow a permission grant when you can also only allow in the foreground. [CHAR LIMIT=25] -->
+ <string name="grant_dialog_button_allow_always">All the time</string>
+
+ <!-- Title for the dialog button to allow a permission grant only when the app is in the foreground. [CHAR LIMIT=25] -->
+ <string name="grant_dialog_button_allow_foreground">While using app</string>
+
+ <!-- Title for the dialog button to allow a change from foreground to background permission grant. [CHAR LIMIT=25] -->
+ <string name="grant_dialog_button_allow_background">All the time</string>
</resources>
diff --git a/PermissionController/res/values-zh-rCN-v34/strings.xml b/PermissionController/res/values-zh-rCN-v34/strings.xml
index 7bebdf9bc..59cfa3e4b 100644
--- a/PermissionController/res/values-zh-rCN-v34/strings.xml
+++ b/PermissionController/res/values-zh-rCN-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"位置信息访问权限"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"针对应用和服务。关闭此设置后,系统仍可能在您拨打紧急电话号码时分享麦克风数据"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"针对应用和服务"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-zh-rHK-v34/strings.xml b/PermissionController/res/values-zh-rHK-v34/strings.xml
index 65ad05bdb..2828357eb 100644
--- a/PermissionController/res/values-zh-rHK-v34/strings.xml
+++ b/PermissionController/res/values-zh-rHK-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"位置資料存取權"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"適用於應用程式和服務。如果關閉此設定,系統仍會在你撥打緊急電話號碼時提供麥克風的資料"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"應用程式和服務"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-zh-rTW-v34/strings.xml b/PermissionController/res/values-zh-rTW-v34/strings.xml
index 533a95e78..4fd5930e2 100644
--- a/PermissionController/res/values-zh-rTW-v34/strings.xml
+++ b/PermissionController/res/values-zh-rTW-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"位置資訊存取權"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"適用於應用程式和服務。即使關閉這項設定,系統仍可能會在你撥打緊急電話號碼時,分享麥克風資料"</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"應用程式和服務"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values-zu-v34/strings.xml b/PermissionController/res/values-zu-v34/strings.xml
index cb348a889..5a9f30778 100644
--- a/PermissionController/res/values-zu-v34/strings.xml
+++ b/PermissionController/res/values-zu-v34/strings.xml
@@ -24,4 +24,10 @@
<string name="location_settings" msgid="8863940440881290182">"Setha indawo"</string>
<string name="mic_toggle_description" msgid="1504101620086616040">"Okwama-app namasevisi. Uma leli sethingi livaliwe, idatha yemakrofoni ingabiwa uma ushayela inombolo yezimo eziphuthumayo."</string>
<string name="location_settings_subtitle" msgid="6846532794702613851">"Okwama-app namasevisi"</string>
+ <!-- no translation found for enhanced_confirmation_dialog_title (2832934608609739884) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_desc (6748252577225517533) -->
+ <skip />
+ <!-- no translation found for enhanced_confirmation_dialog_learn_more (3177813037495926648) -->
+ <skip />
</resources>
diff --git a/PermissionController/res/values/dimens.xml b/PermissionController/res/values/dimens.xml
index f638e89df..53d5341fe 100644
--- a/PermissionController/res/values/dimens.xml
+++ b/PermissionController/res/values/dimens.xml
@@ -77,4 +77,5 @@
<dimen name="privhub_circle_stroke_width">8dp</dimen>
<dimen name="privhub_details_recycler_view_bottom_padding">96dp</dimen>
+
</resources>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index 5e1c7d162..e34e2631b 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -1958,4 +1958,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Summary for showing the last access text for 7 days for Wear [CHAR LIMIT=50] -->
<string name="wear_app_perms_7d_access">Accessed <xliff:g id="time_date" example="Jan 3">%1$s</xliff:g> <xliff:g id="time_date" example="12:42 PM">%2$s</xliff:g></string>
+
+ <!-- A string representing a message (sms, email, etc.) telling the user about a one time password. Used for testing [CHAR LIMIT=NONE] -->
+ <string name="test_otp_msg">Your one time password is 132435</string>
</resources>
diff --git a/PermissionController/res/values/styles.xml b/PermissionController/res/values/styles.xml
index b6acf82a7..55181f066 100644
--- a/PermissionController/res/values/styles.xml
+++ b/PermissionController/res/values/styles.xml
@@ -1038,6 +1038,7 @@
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginStart">16dp</item>
+ <item name="android:background">@null</item>
</style>
<!-- END REQUEST ROLE DIALOG ITEM -->
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index e22b1525f..7ee0851c8 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -141,6 +141,8 @@
minSdkVersion="33" />
<permission name="android.permission.EXECUTE_APP_ACTION"
minSdkVersion="34" />
+ <permission name="android.permission.MANAGE_CONTENT_SUGGESTIONS"
+ minSdkVersion="34" />
<permission name="android.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE"
minSdkVersion="35" />
</permissions>
@@ -683,6 +685,8 @@
<permission name="android.permission.ALWAYS_UPDATE_WALLPAPER" minSdkVersion="35" />
<permission name="android.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE"
minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING"
+ minSdkVersion="35" />
</permissions>
</role>
@@ -1357,6 +1361,12 @@
<permission name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL" minSdkVersion="34" />
<permission name="android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS" minSdkVersion="34" />
<permission name="android.permission.MANAGE_DEVICE_POLICY_CONTENT_PROTECTION" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_QUERY_SYSTEM_UPDATES" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION" minSdkVersion="35" />
+ <permission name="android.permission.MANAGE_DEVICE_POLICY_AUDIT_LOGGING" minSdkVersion="35" />
</permissions>
</role>
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java
index a689db8df..0e1447598 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/WalletRoleBehavior.java
@@ -21,6 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.nfc.cardemulation.HostApduService;
import android.nfc.cardemulation.OffHostApduService;
@@ -29,6 +31,7 @@ import android.os.UserHandle;
import android.permission.flags.Flags;
import android.service.quickaccesswallet.QuickAccessWalletService;
import android.util.ArraySet;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -39,6 +42,9 @@ import com.android.role.controller.model.Role;
import com.android.role.controller.model.RoleBehavior;
import com.android.role.controller.util.UserUtils;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -90,15 +96,14 @@ public class WalletRoleBehavior implements RoleBehavior {
@NonNull
private static Set<String> getQualifyingPackageNamesInternal(@Nullable String packageName,
@NonNull UserHandle user, @NonNull Context context) {
- Set<String> packageNames =
- resolvePackageNames(HostApduService.SERVICE_INTERFACE, packageName, user,
- context);
- packageNames.addAll(
- resolvePackageNames(OffHostApduService.SERVICE_INTERFACE, packageName, user,
- context));
- packageNames.addAll(
- resolvePackageNames(QuickAccessWalletService.SERVICE_INTERFACE, packageName, user,
- context));
+ Set<String> packageNames = resolvePackageNames(QuickAccessWalletService.SERVICE_INTERFACE,
+ packageName, user, context);
+ if (isNfcHostCardEmulationSupported(context)) {
+ packageNames.addAll(getQualifyingApduServicesAsUser(packageName, false, user,
+ context));
+ packageNames.addAll(getQualifyingApduServicesAsUser(packageName, true, user,
+ context));
+ }
return packageNames;
}
@@ -113,8 +118,50 @@ public class WalletRoleBehavior implements RoleBehavior {
Set<String> packageNames = new ArraySet<>();
int resolveInfosSize = resolveInfos.size();
for (int i = 0; i < resolveInfosSize; i++) {
- packageNames.add(resolveInfos.get(i).serviceInfo.packageName);
+ ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
+ if (!serviceInfo.exported) {
+ continue;
+ }
+ packageNames.add(serviceInfo.packageName);
}
return packageNames;
}
+
+ @NonNull
+ private static Set<String> getQualifyingApduServicesAsUser(@Nullable String packageName,
+ boolean onHost, @NonNull UserHandle user, @NonNull Context context) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ PackageManager userPackageManager = userContext.getPackageManager();
+ Intent intent = new Intent(
+ onHost ? HostApduService.SERVICE_INTERFACE : OffHostApduService.SERVICE_INTERFACE)
+ .setPackage(packageName);
+ List<ResolveInfo> resolveInfos = userPackageManager.queryIntentServices(intent,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.GET_META_DATA);
+ Set<String> packageNames = new ArraySet<>();
+ int resolveInfosSize = resolveInfos.size();
+ for (int i = 0; i < resolveInfosSize; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+ ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ if (!serviceInfo.exported) {
+ continue;
+ }
+ ApduServiceInfo apduServiceInfo;
+ try {
+ apduServiceInfo = new ApduServiceInfo(userPackageManager, resolveInfo, onHost);
+ } catch (IOException | XmlPullParserException e) {
+ Log.w(LOG_TAG, "Unable to create ApduServiceInfo for " + resolveInfo, e);
+ continue;
+ }
+ if (apduServiceInfo.hasCategory(CardEmulation.CATEGORY_PAYMENT)) {
+ packageNames.add(resolveInfo.serviceInfo.packageName);
+ }
+ }
+ return packageNames;
+ }
+
+ private static boolean isNfcHostCardEmulationSupported(@NonNull Context context) {
+ return context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ }
}
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 fe062ef53..51730a1df 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
@@ -17,9 +17,12 @@
package com.android.role.controller.model;
import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
+import android.app.ecm.EnhancedConfirmationManager;
import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
@@ -27,6 +30,9 @@ import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.Build;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.permission.flags.Flags;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -970,7 +976,7 @@ public class Role {
* Check whether this role should be visible to user.
*
* @param user the user to check for
- * @param context the `Context` to retrieve system services
+ * @param context the {@code Context} to retrieve system services
*
* @return whether this role should be visible to user
*/
@@ -1000,6 +1006,76 @@ public class Role {
return behavior.isApplicationVisibleAsUser(this, applicationInfo, user, context);
}
+ /**
+ * Check whether this role is restricted and return the {@code Intent} for the restriction if it
+ * is.
+ * <p>
+ * If a role is restricted, it is implied that all applications are restricted for the role as
+ * well.
+ *
+ * @param user the user to check for
+ * @param context the {@code Context} to retrieve system services
+ *
+ * @return the {@code Intent} for the restriction if this role is restricted, or {@code null}
+ * otherwise.
+ */
+ @Nullable
+ public Intent getRestrictionIntentAsUser(@NonNull UserHandle user, @NonNull Context context) {
+ if (SdkLevel.isAtLeastU() && mExclusive) {
+ UserManager userManager = context.getSystemService(UserManager.class);
+ if (userManager.hasUserRestrictionForUser(UserManager.DISALLOW_CONFIG_DEFAULT_APPS,
+ user)) {
+ return new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS)
+ .putExtra(DevicePolicyManager.EXTRA_RESTRICTION,
+ UserManager.DISALLOW_CONFIG_DEFAULT_APPS);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Check whether an application is restricted for this role and return the {@code Intent} for
+ * the restriction if it is.
+ * <p>
+ * If a role is restricted, it is implied that all applications are restricted for the role as
+ * well.
+ *
+ * @param applicationInfo the {@link ApplicationInfo} for the application
+ * @param user the user to check for
+ * @param context the {@code Context} to retrieve system services
+ *
+ * @return the {@code Intent} for the restriction if the application is restricted for this
+ * role, or {@code null} otherwise.
+ */
+ @Nullable
+ public Intent getApplicationRestrictionIntentAsUser(@NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (SdkLevel.isAtLeastV() && Flags.enhancedConfirmationModeApisEnabled()) {
+ Context userContext = UserUtils.getUserContext(context, user);
+ EnhancedConfirmationManager userEnhancedConfirmationManager =
+ userContext.getSystemService(EnhancedConfirmationManager.class);
+ String packageName = applicationInfo.packageName;
+ boolean isRestricted;
+ try {
+ isRestricted = userEnhancedConfirmationManager.isRestricted(packageName, mName);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(LOG_TAG, "Cannot check enhanced confirmation restriction for package: "
+ + packageName, e);
+ isRestricted = false;
+ }
+ if (isRestricted) {
+ try {
+ return userEnhancedConfirmationManager.createRestrictedSettingDialogIntent(
+ packageName, mName);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(LOG_TAG, "Cannot create enhanced confirmation restriction intent for"
+ + " package: " + packageName, e);
+ }
+ }
+ }
+ return getRestrictionIntentAsUser(user, context);
+ }
+
@Override
public String toString() {
return "Role{"
diff --git a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
index 719ef33b5..0ee0e0d01 100644
--- a/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/auto/DrivingDecisionReminderService.kt
@@ -140,6 +140,14 @@ class DrivingDecisionReminderService : Service() {
car.disconnect()
}
}
+
+ fun cancelNotification(context: Context) {
+ val notificationManager = context.getSystemService(NotificationManager::class.java)!!
+ notificationManager.cancel(
+ DrivingDecisionReminderService::class.java.simpleName,
+ Constants.PERMISSION_DECISION_REMINDER_NOTIFICATION_ID
+ )
+ }
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
diff --git a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialog.java b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialog.java
new file mode 100644
index 000000000..c2f62ab8e
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialog.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.ecm;
+
+import android.app.Activity;
+import android.app.ecm.EnhancedConfirmationManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.permission.flags.Flags;
+import android.text.TextUtils;
+
+import androidx.annotation.Keep;
+
+import com.android.modules.utils.build.SdkLevel;
+
+@Keep
+public class EnhancedConfirmationDialog extends Activity implements
+ DialogInterface.OnDismissListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (!SdkLevel.isAtLeastV() || !Flags.enhancedConfirmationModeApisEnabled()) {
+ return;
+ }
+
+ final String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ if (TextUtils.isEmpty(packageName)) {
+ throw new IllegalArgumentException("EXTRA_PACKAGE_NAME cannot be null or empty");
+ }
+ final int uid = getIntent().getIntExtra(Intent.EXTRA_UID, android.os.Process.INVALID_UID);
+ if (uid == android.os.Process.INVALID_UID) {
+ throw new IllegalArgumentException("EXTRA_UID cannot be null or invalid");
+ }
+ final UserHandle user = UserHandle.getUserHandleForUid(uid);
+
+ EnhancedConfirmationDialogHelper dialogHelper = new EnhancedConfirmationDialogHelper(this);
+ dialogHelper
+ .prepareDialogBuilder()
+ .setOnDismissListener(this)
+ .show();
+
+ setClearRestrictionAllowed(packageName, user);
+ }
+
+ private void setClearRestrictionAllowed(String packageName, UserHandle user) {
+ Context userContext = createContextAsUser(user, 0);
+ EnhancedConfirmationManager ecm = userContext.getSystemService(
+ EnhancedConfirmationManager.class);
+ try {
+ ecm.setClearRestrictionAllowed(packageName);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException("unknown package: " + packageName);
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogHelper.java b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogHelper.java
new file mode 100644
index 000000000..c951cb889
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogHelper.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.ecm;
+
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.permissioncontroller.R;
+import com.android.settingslib.HelpUtils;
+
+final class EnhancedConfirmationDialogHelper {
+
+ private final ViewGroup mDialogView;
+ private final Activity mActivity;
+
+ EnhancedConfirmationDialogHelper(Activity activity) {
+ mActivity = activity;
+ mDialogView = (ViewGroup) LayoutInflater.from(mActivity).inflate(
+ R.layout.enhanced_confirmation_dialog, null);
+ }
+
+ public AlertDialog.Builder prepareDialogBuilder() {
+ final String helpUrl = mActivity.getString(
+ R.string.help_url_action_disabled_by_restricted_settings);
+ AlertDialog.Builder builder = new AlertDialog.Builder(mActivity,
+ com.android.settingslib.widget.theme.R.style.Theme_AlertDialog_SettingsLib)
+ .setView(mDialogView)
+ .setPositiveButton(R.string.ok, null)
+ .setNeutralButton(R.string.enhanced_confirmation_dialog_learn_more,
+ (DialogInterface.OnClickListener) (dialog, which) -> {
+ final Intent intent = HelpUtils.getHelpIntent(mActivity, helpUrl,
+ mActivity.getClass().getName());
+ if (intent != null) {
+ mActivity.startActivity(intent);
+ }
+ });
+ return builder;
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
index cc5f156ce..0ebfcd3d7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/PermGroupsPackagesUiInfoLiveData.kt
@@ -21,6 +21,7 @@ import android.app.role.RoleManager
import android.os.Handler
import android.os.Looper
import android.os.UserHandle
+import android.os.UserManager
import androidx.lifecycle.LiveData
import com.android.permissioncontroller.PermissionControllerApplication
import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
@@ -62,6 +63,8 @@ class PermGroupsPackagesUiInfoLiveData(
private val allPackageData = mutableMapOf<String, PermGroupPackagesUiInfo?>()
private lateinit var groupNames: List<String>
+ private val userManager =
+ Utils.getSystemServiceSafe(app.applicationContext, UserManager::class.java)
init {
addSource(groupNamesLiveData) {
@@ -91,12 +94,22 @@ class PermGroupsPackagesUiInfoLiveData(
var grantedSystem = 0
var userInteractedSystem = 0
var firstGrantedSystemPackageName: String? = null
+ val showInSettingsByUsers = HashMap<UserHandle, Boolean>()
for ((packageUserPair, appPermGroup) in appPermGroups) {
if (!appPermGroup.shouldShow) {
continue
}
+ if (!showInSettingsByUsers.containsKey(packageUserPair.second)) {
+ showInSettingsByUsers[packageUserPair.second] =
+ Utils.shouldShowInSettings(packageUserPair.second, userManager)
+ }
+
+ if (showInSettingsByUsers[packageUserPair.second] == false) {
+ continue
+ }
+
if (appPermGroup.isSystem) {
if (isGranted(appPermGroup.permGrantState)) {
if (grantedSystem == 0) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index ddcdf1319..4fd62dc05 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
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.content.Intent.getIntent;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
@@ -34,12 +35,15 @@ import static com.android.permissioncontroller.permission.ui.GrantPermissionsVie
import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.LINKED_TO_PERMISSION_RATIONALE;
import static com.android.permissioncontroller.permission.ui.GrantPermissionsViewHandler.LINKED_TO_SETTINGS;
import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.APP_PERMISSION_REQUEST_CODE;
+import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.ECM_REQUEST_CODE;
import static com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.PHOTO_PICKER_REQUEST_CODE;
import static com.android.permissioncontroller.permission.utils.Utils.getRequestMessage;
import android.Manifest;
import android.app.Activity;
import android.app.KeyguardManager;
+import android.app.ecm.EnhancedConfirmationManager;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -49,6 +53,7 @@ import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
+import android.permission.flags.Flags;
import android.text.Annotation;
import android.text.SpannableString;
import android.text.Spanned;
@@ -104,6 +109,13 @@ public class GrantPermissionsActivity extends SettingsActivity
private static final String KEY_SESSION_ID = GrantPermissionsActivity.class.getName()
+ "_REQUEST_ID";
+ public static final String KEY_RESTRICTED_REQUESTED_PERMISSIONS =
+ GrantPermissionsActivity.class.getName() + "_RESTRICTED_REQUESTED_PERMISSIONS";
+ public static final String KEY_UNRESTRICTED_REQUESTED_PERMISSIONS =
+ GrantPermissionsActivity.class.getName() + "_UNRESTRICTED_REQUESTED_PERMISSIONS";
+ public static final String KEY_ORIGINAL_REQUESTED_PERMISSIONS =
+ GrantPermissionsActivity.class.getName() + "_ORIGINAL_REQUESTED_PERMISSIONS";
+
public static final String ANNOTATION_ID = "link";
public static final int NEXT_BUTTON = 15;
@@ -158,6 +170,17 @@ public class GrantPermissionsActivity extends SettingsActivity
/** The current list of permissions requested, across all current requests for this app */
private List<String> mRequestedPermissions = new ArrayList<>();
+ /**
+ * If any requested permissions are considered restricted by ECM, they will be stored here.
+ */
+ private ArrayList<String> mRestrictedRequestedPermissionGroups = null;
+
+ /**
+ * If any requested permissions are considered restricted by ECM, the non-restricted
+ * permissions will be stored here.
+ */
+ private List<String> mUnrestrictedRequestedPermissions = null;
+
/** A list of permissions requested on an app's behalf by the system. Usually Implicitly
* requested, although this isn't necessarily always the case.
*/
@@ -297,6 +320,56 @@ public class GrantPermissionsActivity extends SettingsActivity
mOriginalRequestedPermissions = mRequestedPermissions.toArray(new String[0]);
+ if (SdkLevel.isAtLeastV() && Flags.enhancedConfirmationModeApisEnabled()) {
+ EnhancedConfirmationManager ecm = getEnhancedConfirmationManager();
+
+ // Retrieve ECM-related persisted permission lists
+ if (icicle != null) {
+ mOriginalRequestedPermissions = icicle.getStringArray(
+ KEY_ORIGINAL_REQUESTED_PERMISSIONS);
+ mRestrictedRequestedPermissionGroups = icicle.getStringArrayList(
+ KEY_RESTRICTED_REQUESTED_PERMISSIONS);
+ mUnrestrictedRequestedPermissions = icicle.getStringArrayList(
+ KEY_UNRESTRICTED_REQUESTED_PERMISSIONS);
+ }
+ // If these lists aren't persisted yet, it means we haven't yet divided
+ // mRequestedPermissions into restricted-vs-unrestricted, so do so.
+ if (mRestrictedRequestedPermissionGroups == null) {
+ String packageName = getCallingPackage();
+ ArraySet<String> restrictedPermGroups = new ArraySet<>();
+ ArrayList<String> unrestrictedPermissions = new ArrayList<>();
+
+ for (String requestedPermission : mRequestedPermissions) {
+ String requestedPermGroup =
+ PermissionMapping.getGroupOfPlatformPermission(requestedPermission);
+ if (restrictedPermGroups.contains(requestedPermGroup)
+ || isPermissionEcmRestricted(ecm, requestedPermission, packageName)) {
+ restrictedPermGroups.add(requestedPermGroup);
+ } else {
+ unrestrictedPermissions.add(requestedPermission);
+ }
+ }
+ mRestrictedRequestedPermissionGroups = new ArrayList<>(restrictedPermGroups);
+ mUnrestrictedRequestedPermissions = unrestrictedPermissions;
+ }
+ // If there are remaining restricted permission groups to process, show the ECM dialog
+ // for the next one, then recreate this activity.
+ if (!mRestrictedRequestedPermissionGroups.isEmpty()) {
+ String nextRestrictedPermissionGroup = mRestrictedRequestedPermissionGroups.remove(
+ 0);
+ try {
+ Intent intent = ecm.createRestrictedSettingDialogIntent(getPackageName(),
+ nextRestrictedPermissionGroup);
+ startActivityForResult(intent, ECM_REQUEST_CODE);
+ return;
+ } catch (PackageManager.NameNotFoundException e) {
+ mRequestedPermissions = mUnrestrictedRequestedPermissions;
+ }
+ } else {
+ mRequestedPermissions = mUnrestrictedRequestedPermissions;
+ }
+ }
+
synchronized (sCurrentGrantRequests) {
mKey = new Pair<>(mTargetPackage, getTaskId());
if (!sCurrentGrantRequests.containsKey(mKey)) {
@@ -390,6 +463,20 @@ public class GrantPermissionsActivity extends SettingsActivity
}
}
+ private EnhancedConfirmationManager getEnhancedConfirmationManager() {
+ Context userContext = Utils.getUserContext(this, Process.myUserHandle());
+ return Utils.getSystemServiceSafe(userContext, EnhancedConfirmationManager.class);
+ }
+
+ private boolean isPermissionEcmRestricted(EnhancedConfirmationManager ecm,
+ String requestedPermission, String packageName) {
+ try {
+ return ecm.isRestricted(packageName, requestedPermission);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
/**
* A new GrantPermissionsActivity has opened for this same package. Merge its requested
* permissions with the original ones set in the intent, and recalculate the grant states.
@@ -713,6 +800,15 @@ public class GrantPermissionsActivity extends SettingsActivity
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
+ if (SdkLevel.isAtLeastV() && Flags.enhancedConfirmationModeApisEnabled()) {
+ outState.putStringArrayList(KEY_RESTRICTED_REQUESTED_PERMISSIONS, new ArrayList<>(
+ mRestrictedRequestedPermissionGroups));
+ outState.putStringArrayList(KEY_UNRESTRICTED_REQUESTED_PERMISSIONS, new ArrayList<>(
+ mUnrestrictedRequestedPermissions));
+ outState.putStringArray(KEY_ORIGINAL_REQUESTED_PERMISSIONS,
+ mOriginalRequestedPermissions);
+ }
+
if (mViewHandler == null || mViewModel == null) {
return;
}
@@ -738,6 +834,12 @@ public class GrantPermissionsActivity extends SettingsActivity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
+ if (SdkLevel.isAtLeastV() && Flags.enhancedConfirmationModeApisEnabled()) {
+ if (requestCode == ECM_REQUEST_CODE) {
+ recreate();
+ return;
+ }
+ }
if (requestCode != APP_PERMISSION_REQUEST_CODE
&& requestCode != PHOTO_PICKER_REQUEST_CODE) {
return;
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
index 99f5c85e4..2350a5d71 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoReviewPermissionDecisionsFragment.kt
@@ -35,6 +35,7 @@ import com.android.permissioncontroller.PermissionControllerStatsLog.RECENT_PERM
import com.android.permissioncontroller.PermissionControllerStatsLog.RECENT_PERMISSION_DECISIONS_INTERACTED__ACTION__VIEW_ALL_CLICKED
import com.android.permissioncontroller.R
import com.android.permissioncontroller.auto.AutoSettingsFrameFragment
+import com.android.permissioncontroller.auto.DrivingDecisionReminderService
import com.android.permissioncontroller.permission.data.v33.PermissionDecision
import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
import com.android.permissioncontroller.permission.ui.model.v33.ReviewPermissionDecisionsViewModel
@@ -98,6 +99,7 @@ class AutoReviewPermissionDecisionsFragment : AutoSettingsFrameFragment() {
requireArguments().containsKey(EXTRA_SOURCE) &&
(requireArguments().getString(EXTRA_SOURCE) == EXTRA_SOURCE_NOTIFICATION)
) {
+ DrivingDecisionReminderService.cancelNotification(requireActivity())
logDecisionReminderNotificationClicked()
}
val factory =
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 20dc50130..76e52ad94 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionAppsFragment.java
@@ -34,6 +34,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.safetycenter.SafetyCenterManager;
import android.util.ArrayMap;
@@ -115,6 +116,7 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
private PermissionUsages mPermissionUsages;
private List<AppPermissionUsage> mAppPermissionUsages = new ArrayList<>();
private Boolean mSensorStatus;
+ private UserManager mUserManager;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -168,6 +170,8 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
mViewModel.getSensorStatusLiveData().observe(this, this::setSensorStatus);
}
}
+
+ mUserManager = Utils.getSystemServiceSafe(getContext(), UserManager.class);
}
@Override
@@ -436,6 +440,9 @@ public final class PermissionAppsFragment extends SettingsWithLargeHeader implem
}
for (Pair<String, UserHandle> packageUserLabel : packages) {
+ if (!Utils.shouldShowInSettings(packageUserLabel.getSecond(), mUserManager)) {
+ continue;
+ }
String packageName = packageUserLabel.getFirst();
UserHandle user = packageUserLabel.getSecond();
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 91b94da9a..dca1cbf3a 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -1371,6 +1371,7 @@ class GrantPermissionsViewModel(
companion object {
const val APP_PERMISSION_REQUEST_CODE = 1
const val PHOTO_PICKER_REQUEST_CODE = 2
+ const val ECM_REQUEST_CODE = 3
const val SAVED_REQUEST_CODE_KEY = "saved_request_code"
private const val STATE_UNKNOWN = 0
private const val STATE_GRANTED = 1
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
index 47b5e2ad1..ed4e937d1 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
@@ -21,9 +21,6 @@ import android.content.Context
import android.content.ContextWrapper
import android.graphics.drawable.Drawable
import androidx.compose.foundation.Image
-import androidx.compose.foundation.focusable
-import androidx.compose.foundation.gestures.animateScrollBy
-import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
@@ -34,22 +31,17 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
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.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -71,8 +63,8 @@ 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 com.android.permissioncontroller.permission.ui.wear.elements.rotaryinput.rotaryWithScroll
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme
-import kotlinx.coroutines.launch
/**
* Screen that contains a list of items defined using the [content] parameter, adds the time text
@@ -152,21 +144,16 @@ internal fun Scaffold(
val focusRequester = remember { FocusRequester() }
val listState = remember { ScalingLazyListState(initialCenterItemIndex = initialCenterIndex) }
- val coroutineScope = rememberCoroutineScope()
WearPermissionTheme {
Scaffold(
+ // TODO: Use a rotary modifier from Wear Compose once Wear Compose 1.4 is landed.
+ // (b/325560444)
modifier =
- Modifier.onRotaryScrollEvent {
- coroutineScope.launch {
- listState.scrollBy(it.verticalScrollPixels)
- listState.animateScrollBy(0f)
- }
- true
- }
- .focusRequester(focusRequester)
- .focusable()
- .semantics { testTagsAsResourceId = true },
+ Modifier.rotaryWithScroll(
+ scrollableState = listState,
+ focusRequester = focusRequester
+ ),
timeText = {
if (showTimeText && !isLoading) {
TimeText(
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Haptics.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Haptics.kt
new file mode 100644
index 000000000..817bf7efe
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Haptics.kt
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.rotaryinput
+
+import android.os.Build
+import android.view.View
+import androidx.compose.foundation.gestures.ScrollableState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalView
+import kotlin.math.abs
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.withContext
+
+// This file is a copy of Haptics.kt from Horologist (go/horologist),
+// remove it once Wear Compose 1.4 is landed (b/325560444).
+
+private const val DEBUG = false
+
+/** Debug logging that can be enabled. */
+private inline fun debugLog(generateMsg: () -> String) {
+ if (DEBUG) {
+ println("RotaryHaptics: ${generateMsg()}")
+ }
+}
+
+/**
+ * Throttling events within specified timeframe. Only first and last events will be received. For a
+ * flow emitting elements 1 to 30, with a 100ms delay between them:
+ * ```
+ * val flow = flow {
+ * for (i in 1..30) {
+ * delay(100)
+ * emit(i)
+ * }
+ * }
+ * ```
+ *
+ * With timeframe=1000 only those integers will be received: 1, 10, 20, 30 .
+ */
+internal fun <T> Flow<T>.throttleLatest(timeframe: Long): Flow<T> = flow {
+ conflate().collect {
+ emit(it)
+ delay(timeframe)
+ }
+}
+
+/** Handles haptics for rotary usage */
+interface RotaryHapticHandler {
+
+ /** Handles haptics when scroll is used */
+ fun handleScrollHaptic(scrollDelta: Float)
+
+ /** Handles haptics when scroll with snap is used */
+ fun handleSnapHaptic(scrollDelta: Float)
+}
+
+/**
+ * Default implementation of [RotaryHapticHandler]. It handles haptic feedback based on the
+ * [scrollableState], scrolled pixels and [hapticsThresholdPx]. Haptic is not fired in this class,
+ * instead it's sent to [hapticsChannel] where it'll performed later.
+ *
+ * @param scrollableState Haptic performed based on this state
+ * @param hapticsChannel Channel to which haptic events will be sent
+ * @param hapticsThresholdPx A scroll threshold after which haptic is produced.
+ */
+class DefaultRotaryHapticHandler(
+ private val scrollableState: ScrollableState,
+ private val hapticsChannel: Channel<RotaryHapticsType>,
+ private val hapticsThresholdPx: Long = 50,
+) : RotaryHapticHandler {
+
+ private var overscrollHapticTriggered = false
+ private var currScrollPosition = 0f
+ private var prevHapticsPosition = 0f
+
+ override fun handleScrollHaptic(scrollDelta: Float) {
+ if (
+ (scrollDelta > 0 && !scrollableState.canScrollForward) ||
+ (scrollDelta < 0 && !scrollableState.canScrollBackward)
+ ) {
+ if (!overscrollHapticTriggered) {
+ trySendHaptic(RotaryHapticsType.ScrollLimit)
+ overscrollHapticTriggered = true
+ }
+ } else {
+ overscrollHapticTriggered = false
+ currScrollPosition += scrollDelta
+ val diff = abs(currScrollPosition - prevHapticsPosition)
+
+ if (diff >= hapticsThresholdPx) {
+ trySendHaptic(RotaryHapticsType.ScrollTick)
+ prevHapticsPosition = currScrollPosition
+ }
+ }
+ }
+
+ override fun handleSnapHaptic(scrollDelta: Float) {
+ if (
+ (scrollDelta > 0 && !scrollableState.canScrollForward) ||
+ (scrollDelta < 0 && !scrollableState.canScrollBackward)
+ ) {
+ if (!overscrollHapticTriggered) {
+ trySendHaptic(RotaryHapticsType.ScrollLimit)
+ overscrollHapticTriggered = true
+ }
+ } else {
+ overscrollHapticTriggered = false
+ trySendHaptic(RotaryHapticsType.ScrollItemFocus)
+ }
+ }
+
+ private fun trySendHaptic(rotaryHapticsType: RotaryHapticsType) {
+ // Ok to ignore the ChannelResult because we default to capacity = 2 and DROP_OLDEST
+ @Suppress("UNUSED_VARIABLE") val unused = hapticsChannel.trySend(rotaryHapticsType)
+ }
+}
+
+/** Interface for Rotary haptic feedback */
+interface RotaryHapticFeedback {
+ fun performHapticFeedback(type: RotaryHapticsType)
+}
+
+/** Rotary haptic types */
+@JvmInline
+value class RotaryHapticsType(private val type: Int) {
+ companion object {
+ /**
+ * A scroll ticking haptic. Similar to texture haptic - performed each time when a
+ * scrollable content is scrolled by a certain distance
+ */
+ val ScrollTick: RotaryHapticsType = RotaryHapticsType(1)
+
+ /**
+ * An item focus (snap) haptic. Performed when a scrollable content is snapped to a specific
+ * item.
+ */
+ val ScrollItemFocus: RotaryHapticsType = RotaryHapticsType(2)
+
+ /**
+ * A limit(overscroll) haptic. Performed when a list reaches the limit (start or end) and
+ * can't scroll further
+ */
+ val ScrollLimit: RotaryHapticsType = RotaryHapticsType(3)
+ }
+}
+
+/** Remember disabled haptics handler */
+@Composable
+fun rememberDisabledHaptic(): RotaryHapticHandler = remember {
+ object : RotaryHapticHandler {
+
+ override fun handleScrollHaptic(scrollDelta: Float) {
+ // Do nothing
+ }
+
+ override fun handleSnapHaptic(scrollDelta: Float) {
+ // Do nothing
+ }
+ }
+}
+
+/**
+ * Remember rotary haptic handler.
+ *
+ * @param scrollableState A scrollableState, used to determine whether the end of the scrollable was
+ * reached or not.
+ * @param throttleThresholdMs Throttling events within specified timeframe. Only first and last
+ * events will be received. Check [throttleLatest] for more info.
+ * @param hapticsThresholdPx A scroll threshold after which haptic is produced.
+ * @param hapticsChannel Channel to which haptic events will be sent
+ * @param rotaryHaptics Interface for Rotary haptic feedback which performs haptics
+ */
+@Composable
+fun rememberRotaryHapticHandler(
+ scrollableState: ScrollableState,
+ throttleThresholdMs: Long = 30,
+ hapticsThresholdPx: Long = 50,
+ hapticsChannel: Channel<RotaryHapticsType> = rememberHapticChannel(),
+ rotaryHaptics: RotaryHapticFeedback = rememberDefaultRotaryHapticFeedback(),
+): RotaryHapticHandler {
+ return remember(scrollableState, hapticsChannel, rotaryHaptics) {
+ DefaultRotaryHapticHandler(scrollableState, hapticsChannel, hapticsThresholdPx)
+ }
+ .apply {
+ LaunchedEffect(hapticsChannel) {
+ hapticsChannel.receiveAsFlow().throttleLatest(throttleThresholdMs).collect {
+ hapticType ->
+ // 'withContext' launches performHapticFeedback in a separate thread,
+ // as otherwise it produces a visible lag (b/219776664)
+ val currentTime = System.currentTimeMillis()
+ debugLog { "Haptics started" }
+ withContext(Dispatchers.Default) {
+ debugLog {
+ "Performing haptics, delay: " +
+ "${System.currentTimeMillis() - currentTime}"
+ }
+ rotaryHaptics.performHapticFeedback(hapticType)
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun rememberHapticChannel() = remember {
+ Channel<RotaryHapticsType>(
+ capacity = 2,
+ onBufferOverflow = BufferOverflow.DROP_OLDEST,
+ )
+}
+
+@Composable
+public fun rememberDefaultRotaryHapticFeedback(): RotaryHapticFeedback =
+ LocalView.current.let { view -> remember { findDeviceSpecificHapticFeedback(view) } }
+
+internal fun findDeviceSpecificHapticFeedback(view: View): RotaryHapticFeedback =
+ if (isSamsungWatch()) {
+ SamsungWatchHapticFeedback(view)
+ } else {
+ DefaultRotaryHapticFeedback(view)
+ }
+
+/** Default Rotary implementation for [RotaryHapticFeedback] */
+class DefaultRotaryHapticFeedback(private val view: View) : RotaryHapticFeedback {
+
+ override fun performHapticFeedback(
+ type: RotaryHapticsType,
+ ) {
+ when (type) {
+ RotaryHapticsType.ScrollItemFocus -> {
+ view.performHapticFeedback(SCROLL_ITEM_FOCUS)
+ }
+ RotaryHapticsType.ScrollTick -> {
+ view.performHapticFeedback(SCROLL_TICK)
+ }
+ RotaryHapticsType.ScrollLimit -> {
+ view.performHapticFeedback(SCROLL_LIMIT)
+ }
+ }
+ }
+
+ private companion object {
+ // Hidden constants from HapticFeedbackConstants
+ const val SCROLL_TICK: Int = 18
+ const val SCROLL_ITEM_FOCUS: Int = 19
+ const val SCROLL_LIMIT: Int = 20
+ }
+}
+
+/** Implementation of [RotaryHapticFeedback] for Samsung devices */
+private class SamsungWatchHapticFeedback(private val view: View) : RotaryHapticFeedback {
+ override fun performHapticFeedback(
+ type: RotaryHapticsType,
+ ) {
+ when (type) {
+ RotaryHapticsType.ScrollItemFocus -> {
+ view.performHapticFeedback(102)
+ }
+ RotaryHapticsType.ScrollTick -> {
+ view.performHapticFeedback(102)
+ }
+ RotaryHapticsType.ScrollLimit -> {
+ view.performHapticFeedback(50107)
+ }
+ }
+ }
+}
+
+private fun isSamsungWatch(): Boolean = Build.MANUFACTURER.contains("Samsung", ignoreCase = true)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Rotary.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Rotary.kt
new file mode 100644
index 000000000..b96bb3f5b
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/Rotary.kt
@@ -0,0 +1,1187 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.rotaryinput
+
+import android.view.ViewConfiguration
+import androidx.compose.animation.core.AnimationState
+import androidx.compose.animation.core.CubicBezierEasing
+import androidx.compose.animation.core.Easing
+import androidx.compose.animation.core.FastOutSlowInEasing
+import androidx.compose.animation.core.SpringSpec
+import androidx.compose.animation.core.animateTo
+import androidx.compose.animation.core.copy
+import androidx.compose.animation.core.spring
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.MutatePriority
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.gestures.FlingBehavior
+import androidx.compose.foundation.gestures.ScrollableDefaults
+import androidx.compose.foundation.gestures.ScrollableState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.remember
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.input.rotary.onRotaryScrollEvent
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.util.lerp
+import androidx.wear.compose.foundation.ExperimentalWearFoundationApi
+import androidx.wear.compose.foundation.rememberActiveFocusRequester
+import kotlin.math.abs
+import kotlin.math.absoluteValue
+import kotlin.math.sign
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.async
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.flow.transformLatest
+
+// This file is a copy of Rotary.kt from Horologist (go/horologist),
+// remove it once Wear Compose 1.4 is landed (b/325560444).
+
+private const val DEBUG = false
+
+/** Debug logging that can be enabled. */
+private inline fun debugLog(generateMsg: () -> String) {
+ if (DEBUG) {
+ println("RotaryScroll: ${generateMsg()}")
+ }
+}
+
+/**
+ * A modifier which connects rotary events with scrollable. This modifier supports fling.
+ *
+ * Fling algorithm:
+ * - A scroll with RSB/ Bezel happens.
+ * - If this is a first rotary event after the threshold ( by default 200ms), a new scroll session
+ * starts by resetting all necessary parameters
+ * - A delta value is added into VelocityTracker and a new speed is calculated.
+ * - If the current speed is bigger than the previous one, this value is remembered as a latest
+ * fling speed with a timestamp
+ * - After each scroll event a fling countdown starts ( by default 70ms) which resets if new scroll
+ * event is received
+ * - If fling countdown is finished - it means that the finger was probably raised from RSB, there
+ * will be no other events and probably this is the last event during this session. After it a
+ * fling is triggered.
+ * - Fling is stopped when a new scroll event happens
+ *
+ * The screen containing the scrollable item should request the focus by calling [requestFocus]
+ * method
+ *
+ * ```
+ * LaunchedEffect(Unit) {
+ * focusRequester.requestFocus()
+ * }
+ * ```
+ *
+ * @param focusRequester Requests the focus for rotary input
+ * @param scrollableState Scrollable state which will be scrolled while receiving rotary events
+ * @param flingBehavior Logic describing fling behavior.
+ * @param rotaryHaptics Class which will handle haptic feedback
+ * @param reverseDirection Reverse the direction of scrolling. Should be aligned with Scrollable
+ * `reverseDirection` parameter
+ */
+@Suppress("ComposableModifierFactory")
+@Deprecated(
+ "Use rotaryWithScroll instead",
+ ReplaceWith(
+ "this.rotaryWithScroll(scrollableState, focusRequester, " +
+ "flingBehavior, rotaryHaptics, reverseDirection)",
+ ),
+)
+@Composable
+public fun Modifier.rotaryWithFling(
+ focusRequester: FocusRequester,
+ scrollableState: ScrollableState,
+ flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
+ rotaryHaptics: RotaryHapticHandler = rememberRotaryHapticHandler(scrollableState),
+ reverseDirection: Boolean = false,
+): Modifier =
+ rotaryHandler(
+ rotaryScrollHandler =
+ RotaryDefaults.rememberFlingHandler(scrollableState, flingBehavior),
+ reverseDirection = reverseDirection,
+ rotaryHaptics = rotaryHaptics,
+ )
+ .focusRequester(focusRequester)
+ .focusable()
+
+/**
+ * A modifier which connects rotary events with scrollable. This modifier supports scroll with
+ * fling.
+ *
+ * @param scrollableState Scrollable state which will be scrolled while receiving rotary events
+ * @param focusRequester Requests the focus for rotary input. By default comes from
+ * [rememberActiveFocusRequester], which is used with [HierarchicalFocusCoordinator]
+ * @param flingBehavior Logic describing fling behavior. If null fling will not happen.
+ * @param rotaryHaptics Class which will handle haptic feedback
+ * @param reverseDirection Reverse the direction of scrolling. Should be aligned with Scrollable
+ * `reverseDirection` parameter
+ */
+@OptIn(ExperimentalWearFoundationApi::class)
+@Suppress("ComposableModifierFactory")
+@Composable
+public fun Modifier.rotaryWithScroll(
+ scrollableState: ScrollableState,
+ focusRequester: FocusRequester = rememberActiveFocusRequester(),
+ flingBehavior: FlingBehavior? = ScrollableDefaults.flingBehavior(),
+ rotaryHaptics: RotaryHapticHandler = rememberRotaryHapticHandler(scrollableState),
+ reverseDirection: Boolean = false,
+): Modifier =
+ rotaryHandler(
+ rotaryScrollHandler =
+ RotaryDefaults.rememberFlingHandler(scrollableState, flingBehavior),
+ reverseDirection = reverseDirection,
+ rotaryHaptics = rotaryHaptics,
+ )
+ .focusRequester(focusRequester)
+ .focusable()
+
+/**
+ * A modifier which connects rotary events with scrollable. This modifier supports snap.
+ *
+ * @param focusRequester Requests the focus for rotary input. By default comes from
+ * [rememberActiveFocusRequester], which is used with [HierarchicalFocusCoordinator]
+ * @param rotaryScrollAdapter A connection between scrollable objects and rotary events
+ * @param rotaryHaptics Class which will handle haptic feedback
+ * @param reverseDirection Reverse the direction of scrolling. Should be aligned with Scrollable
+ * `reverseDirection` parameter
+ */
+@OptIn(ExperimentalWearFoundationApi::class)
+@Suppress("ComposableModifierFactory")
+@Composable
+public fun Modifier.rotaryWithSnap(
+ rotaryScrollAdapter: RotaryScrollAdapter,
+ focusRequester: FocusRequester = rememberActiveFocusRequester(),
+ snapParameters: SnapParameters = RotaryDefaults.snapParametersDefault(),
+ rotaryHaptics: RotaryHapticHandler =
+ rememberRotaryHapticHandler(rotaryScrollAdapter.scrollableState),
+ reverseDirection: Boolean = false,
+): Modifier =
+ rotaryHandler(
+ rotaryScrollHandler =
+ RotaryDefaults.rememberSnapHandler(rotaryScrollAdapter, snapParameters),
+ reverseDirection = reverseDirection,
+ rotaryHaptics = rotaryHaptics,
+ )
+ .focusRequester(focusRequester)
+ .focusable()
+
+/** An adapter which connects scrollableState to Rotary */
+interface RotaryScrollAdapter {
+
+ /** A scrollable state. Used for performing scroll when Rotary events received */
+ val scrollableState: ScrollableState
+
+ /** Average size of an item. Used for estimating the scrollable distance */
+ fun averageItemSize(): Float
+
+ /** A current item index. Used for scrolling */
+ fun currentItemIndex(): Int
+
+ /** An offset from the centre or the border of the current item. */
+ fun currentItemOffset(): Float
+
+ /** The total count of items in [scrollableState] */
+ fun totalItemsCount(): Int
+}
+
+/** Defaults for rotary modifiers */
+object RotaryDefaults {
+
+ /**
+ * Handles scroll with fling.
+ *
+ * @param scrollableState Scrollable state which will be scrolled while receiving rotary events
+ * @param flingBehavior Logic describing Fling behavior. If null - fling will not happen
+ * @param isLowRes Whether the input is Low-res (a bezel) or high-res(a crown/rsb)
+ */
+ @Composable
+ fun rememberFlingHandler(
+ scrollableState: ScrollableState,
+ flingBehavior: FlingBehavior? = null,
+ isLowRes: Boolean = isLowResInput(),
+ ): RotaryScrollHandler {
+ val viewConfiguration = ViewConfiguration.get(LocalContext.current)
+
+ return remember(scrollableState, flingBehavior, isLowRes) {
+ debugLog { "isLowRes : $isLowRes" }
+ fun rotaryFlingBehavior() =
+ flingBehavior?.run {
+ DefaultRotaryFlingBehavior(
+ scrollableState,
+ flingBehavior,
+ viewConfiguration,
+ flingTimeframe =
+ if (isLowRes) lowResFlingTimeframe else highResFlingTimeframe,
+ )
+ }
+
+ fun scrollBehavior() = AnimationScrollBehavior(scrollableState)
+
+ if (isLowRes) {
+ LowResRotaryScrollHandler(
+ rotaryFlingBehaviorFactory = { rotaryFlingBehavior() },
+ scrollBehaviorFactory = { scrollBehavior() },
+ )
+ } else {
+ HighResRotaryScrollHandler(
+ rotaryFlingBehaviorFactory = { rotaryFlingBehavior() },
+ scrollBehaviorFactory = { scrollBehavior() },
+ )
+ }
+ }
+ }
+
+ /**
+ * Handles scroll with snap
+ *
+ * @param rotaryScrollAdapter A connection between scrollable objects and rotary events
+ * @param snapParameters Snap parameters
+ */
+ @Composable
+ fun rememberSnapHandler(
+ rotaryScrollAdapter: RotaryScrollAdapter,
+ snapParameters: SnapParameters = snapParametersDefault(),
+ isLowRes: Boolean = isLowResInput(),
+ ): RotaryScrollHandler {
+ return remember(rotaryScrollAdapter, snapParameters) {
+ if (isLowRes) {
+ LowResSnapHandler(
+ snapBehaviourFactory = {
+ DefaultSnapBehavior(rotaryScrollAdapter, snapParameters)
+ },
+ )
+ } else {
+ HighResSnapHandler(
+ resistanceFactor = snapParameters.resistanceFactor,
+ thresholdBehaviorFactory = {
+ ThresholdBehavior(
+ rotaryScrollAdapter,
+ snapParameters.thresholdDivider,
+ )
+ },
+ snapBehaviourFactory = {
+ DefaultSnapBehavior(rotaryScrollAdapter, snapParameters)
+ },
+ scrollBehaviourFactory = {
+ AnimationScrollBehavior(rotaryScrollAdapter.scrollableState)
+ },
+ )
+ }
+ }
+ }
+
+ /** Returns default [SnapParameters] */
+ fun snapParametersDefault(): SnapParameters =
+ SnapParameters(
+ snapOffset = 0,
+ thresholdDivider = 1.5f,
+ resistanceFactor = 3f,
+ )
+
+ /** Returns whether the input is Low-res (a bezel) or high-res(a crown/rsb). */
+ @Composable
+ fun isLowResInput(): Boolean =
+ LocalContext.current.packageManager.hasSystemFeature(
+ "android.hardware.rotaryencoder.lowres"
+ )
+
+ private val lowResFlingTimeframe: Long = 100L
+ private val highResFlingTimeframe: Long = 30L
+}
+
+/**
+ * Parameters used for snapping
+ *
+ * @param snapOffset an optional offset to be applied when snapping the item. After the snap the
+ * snapped items offset will be [snapOffset].
+ */
+class SnapParameters(
+ val snapOffset: Int,
+ val thresholdDivider: Float,
+ val resistanceFactor: Float,
+) {
+ /** Returns a snapping offset in [Dp] */
+ @Composable
+ fun snapOffsetDp(): Dp {
+ return with(LocalDensity.current) { snapOffset.toDp() }
+ }
+}
+
+/** An interface for handling scroll events */
+interface RotaryScrollHandler {
+ /**
+ * Handles scrolling events
+ *
+ * @param coroutineScope A scope for performing async actions
+ * @param event A scrollable event from rotary input, containing scrollable delta and timestamp
+ * @param rotaryHaptics
+ */
+ suspend fun handleScrollEvent(
+ coroutineScope: CoroutineScope,
+ event: TimestampedDelta,
+ rotaryHaptics: RotaryHapticHandler,
+ )
+}
+
+/** An interface for scrolling behavior */
+interface RotaryScrollBehavior {
+ /** Handles scroll event to [targetValue] */
+ suspend fun handleEvent(targetValue: Float)
+}
+
+/** Default implementation of [RotaryFlingBehavior] */
+class DefaultRotaryFlingBehavior(
+ private val scrollableState: ScrollableState,
+ private val flingBehavior: FlingBehavior,
+ viewConfiguration: ViewConfiguration,
+ private val flingTimeframe: Long,
+) : RotaryFlingBehavior {
+
+ // A time range during which the fling is valid.
+ // For simplicity it's twice as long as [flingTimeframe]
+ private val timeRangeToFling = flingTimeframe * 2
+
+ // A default fling factor for making fling slower
+ private val flingScaleFactor = 0.7f
+
+ private var previousVelocity = 0f
+
+ private val rotaryVelocityTracker = RotaryVelocityTracker()
+
+ private val minFlingSpeed = viewConfiguration.scaledMinimumFlingVelocity.toFloat()
+ private val maxFlingSpeed = viewConfiguration.scaledMaximumFlingVelocity.toFloat()
+ private var latestEventTimestamp: Long = 0
+
+ private var flingVelocity: Float = 0f
+ private var flingTimestamp: Long = 0
+
+ override fun startFlingTracking(timestamp: Long) {
+ rotaryVelocityTracker.start(timestamp)
+ latestEventTimestamp = timestamp
+ previousVelocity = 0f
+ }
+
+ override fun observeEvent(timestamp: Long, delta: Float) {
+ rotaryVelocityTracker.move(timestamp, delta)
+ latestEventTimestamp = timestamp
+ }
+
+ override suspend fun trackFling(beforeFling: () -> Unit) {
+ val currentVelocity = rotaryVelocityTracker.velocity
+ debugLog { "currentVelocity: $currentVelocity" }
+
+ if (abs(currentVelocity) >= abs(previousVelocity)) {
+ flingTimestamp = latestEventTimestamp
+ flingVelocity = currentVelocity * flingScaleFactor
+ }
+ previousVelocity = currentVelocity
+
+ // Waiting for a fixed amount of time before checking the fling
+ delay(flingTimeframe)
+
+ // For making a fling 2 criteria should be met:
+ // 1) no more than
+ // `rangeToFling` ms should pass between last fling detection
+ // and the time of last motion event
+ // 2) flingVelocity should exceed the minFlingSpeed
+ debugLog {
+ "Check fling: flingVelocity: $flingVelocity " +
+ "minFlingSpeed: $minFlingSpeed, maxFlingSpeed: $maxFlingSpeed"
+ }
+ if (
+ latestEventTimestamp - flingTimestamp < timeRangeToFling &&
+ abs(flingVelocity) > minFlingSpeed
+ ) {
+ // Stops scrollAnimationCoroutine because a fling will be performed
+ beforeFling()
+ val velocity = flingVelocity.coerceIn(-maxFlingSpeed, maxFlingSpeed)
+ scrollableState.scroll(MutatePriority.UserInput) {
+ with(flingBehavior) {
+ debugLog { "Flinging with velocity $velocity" }
+ performFling(velocity)
+ }
+ }
+ }
+ }
+}
+
+/** An interface for flinging with rotary */
+interface RotaryFlingBehavior {
+
+ /** Observing new event within a fling tracking session with new timestamp and delta */
+ fun observeEvent(timestamp: Long, delta: Float)
+
+ /** Performing fling if necessary and calling [beforeFling] lambda before it is triggered */
+ suspend fun trackFling(beforeFling: () -> Unit)
+
+ /** Starts a new fling tracking session with specified timestamp */
+ fun startFlingTracking(timestamp: Long)
+}
+
+/** An interface for snapping with rotary */
+interface RotarySnapBehavior {
+
+ /**
+ * Preparing snapping. This method should be called before [snapToTargetItem] is called.
+ *
+ * Snapping is done for current + [moveForElements] items.
+ *
+ * If [sequentialSnap] is true, items are summed up together. For example, if
+ * [prepareSnapForItems] is called with [moveForElements] = 2, 3, 5 -> then the snapping will
+ * happen to current + 10 items
+ *
+ * If [sequentialSnap] is false, then [moveForElements] are not summed up together.
+ */
+ fun prepareSnapForItems(moveForElements: Int, sequentialSnap: Boolean)
+
+ /** Performs snapping to the closest item. */
+ suspend fun snapToClosestItem()
+
+ /** Returns true if top edge was reached */
+ fun topEdgeReached(): Boolean
+
+ /** Returns true if bottom edge was reached */
+ fun bottomEdgeReached(): Boolean
+
+ /** Performs snapping to the specified in [prepareSnapForItems] element */
+ suspend fun snapToTargetItem()
+}
+
+/**
+ * A rotary event object which contains a [timestamp] of the rotary event and a scrolled [delta].
+ */
+data class TimestampedDelta(val timestamp: Long, val delta: Float)
+
+/**
+ * Animation implementation of [RotaryScrollBehavior]. This class does a smooth animation when the
+ * scroll by N pixels is done. This animation works well on Rsb(high-res) and Bezel(low-res)
+ * devices.
+ */
+class AnimationScrollBehavior(
+ private val scrollableState: ScrollableState,
+) : RotaryScrollBehavior {
+ private var sequentialAnimation = false
+ private var scrollAnimation = AnimationState(0f)
+ private var prevPosition = 0f
+
+ override suspend fun handleEvent(targetValue: Float) {
+ scrollableState.scroll(MutatePriority.UserInput) {
+ debugLog { "ScrollAnimation value before start: ${scrollAnimation.value}" }
+
+ scrollAnimation.animateTo(
+ targetValue,
+ animationSpec = spring(),
+ sequentialAnimation = sequentialAnimation,
+ ) {
+ val delta = value - prevPosition
+ debugLog { "Animated by $delta, value: $value" }
+ scrollBy(delta)
+ prevPosition = value
+ sequentialAnimation = value != this.targetValue
+ }
+ }
+ }
+}
+
+/**
+ * An animated implementation of [RotarySnapBehavior]. Uses animateScrollToItem method for snapping
+ * to the Nth item
+ */
+class DefaultSnapBehavior(
+ private val rotaryScrollAdapter: RotaryScrollAdapter,
+ private val snapParameters: SnapParameters,
+) : RotarySnapBehavior {
+ private var snapTarget: Int = rotaryScrollAdapter.currentItemIndex()
+ private var sequentialSnap: Boolean = false
+
+ private var anim = AnimationState(0f)
+ private var expectedDistance = 0f
+
+ private val defaultStiffness = 200f
+ private var snapTargetUpdated = true
+
+ override fun prepareSnapForItems(moveForElements: Int, sequentialSnap: Boolean) {
+ this.sequentialSnap = sequentialSnap
+ if (sequentialSnap) {
+ snapTarget += moveForElements
+ } else {
+ snapTarget = rotaryScrollAdapter.currentItemIndex() + moveForElements
+ }
+ snapTargetUpdated = true
+ snapTarget = snapTarget.coerceIn(0 until rotaryScrollAdapter.totalItemsCount())
+ }
+
+ override suspend fun snapToClosestItem() {
+ // Snapping to the closest item by using performFling method with 0 speed
+ rotaryScrollAdapter.scrollableState.scroll(MutatePriority.UserInput) {
+ debugLog { "snap to closest item" }
+ var prevPosition = 0f
+ AnimationState(0f).animateTo(
+ targetValue = -rotaryScrollAdapter.currentItemOffset(),
+ animationSpec = tween(durationMillis = 100, easing = FastOutSlowInEasing),
+ ) {
+ val animDelta = value - prevPosition
+ scrollBy(animDelta)
+ prevPosition = value
+ }
+ snapTarget = rotaryScrollAdapter.currentItemIndex()
+ }
+ }
+
+ override fun topEdgeReached(): Boolean = snapTarget <= 0
+
+ override fun bottomEdgeReached(): Boolean =
+ snapTarget >= rotaryScrollAdapter.totalItemsCount() - 1
+
+ override suspend fun snapToTargetItem() {
+ if (sequentialSnap) {
+ anim = anim.copy(0f)
+ } else {
+ anim = AnimationState(0f)
+ }
+ rotaryScrollAdapter.scrollableState.scroll(MutatePriority.UserInput) {
+ // If snapTargetUpdated is true - then the target was updated so we
+ // need to do snap again
+ while (snapTargetUpdated) {
+ snapTargetUpdated = false
+ var latestCenterItem: Int
+ var continueFirstScroll = true
+ debugLog { "snapTarget $snapTarget" }
+ while (continueFirstScroll) {
+ latestCenterItem = rotaryScrollAdapter.currentItemIndex()
+ anim = anim.copy(0f)
+ expectedDistance = expectedDistanceTo(snapTarget, snapParameters.snapOffset)
+ debugLog {
+ "expectedDistance = $expectedDistance, " +
+ "scrollableState.centerItemScrollOffset " +
+ "${rotaryScrollAdapter.currentItemOffset()}"
+ }
+ continueFirstScroll = false
+ var prevPosition = 0f
+
+ anim.animateTo(
+ expectedDistance,
+ animationSpec =
+ SpringSpec(
+ stiffness = defaultStiffness,
+ visibilityThreshold = 0.1f,
+ ),
+ sequentialAnimation = (anim.velocity != 0f),
+ ) {
+ val animDelta = value - prevPosition
+ debugLog {
+ "First animation, value:$value, velocity:$velocity, " +
+ "animDelta:$animDelta"
+ }
+
+ // Exit animation if snap target was updated
+ if (snapTargetUpdated) cancelAnimation()
+
+ scrollBy(animDelta)
+ prevPosition = value
+
+ if (latestCenterItem != rotaryScrollAdapter.currentItemIndex()) {
+ continueFirstScroll = true
+ cancelAnimation()
+ return@animateTo
+ }
+
+ debugLog { "centerItemIndex = ${rotaryScrollAdapter.currentItemIndex()}" }
+ if (rotaryScrollAdapter.currentItemIndex() == snapTarget) {
+ debugLog { "Target is visible. Cancelling first animation" }
+ debugLog {
+ "scrollableState.centerItemScrollOffset " +
+ "${rotaryScrollAdapter.currentItemOffset()}"
+ }
+ expectedDistance = -rotaryScrollAdapter.currentItemOffset()
+ continueFirstScroll = false
+ cancelAnimation()
+ return@animateTo
+ }
+ }
+ }
+ // Exit animation if snap target was updated
+ if (snapTargetUpdated) continue
+
+ anim = anim.copy(0f)
+ var prevPosition = 0f
+ anim.animateTo(
+ expectedDistance,
+ animationSpec =
+ SpringSpec(
+ stiffness = defaultStiffness,
+ visibilityThreshold = 0.1f,
+ ),
+ sequentialAnimation = (anim.velocity != 0f),
+ ) {
+ // Exit animation if snap target was updated
+ if (snapTargetUpdated) cancelAnimation()
+
+ val animDelta = value - prevPosition
+ debugLog { "Final animation. velocity:$velocity, animDelta:$animDelta" }
+ scrollBy(animDelta)
+ prevPosition = value
+ }
+ }
+ }
+ }
+
+ private fun expectedDistanceTo(index: Int, targetScrollOffset: Int): Float {
+ val averageSize = rotaryScrollAdapter.averageItemSize()
+ val indexesDiff = index - rotaryScrollAdapter.currentItemIndex()
+ debugLog { "Average size $averageSize" }
+ return (averageSize * indexesDiff) + targetScrollOffset -
+ rotaryScrollAdapter.currentItemOffset()
+ }
+}
+
+/**
+ * A modifier which handles rotary events. It accepts ScrollHandler as the input - a class where
+ * main logic about how scroll should be handled is lying
+ */
+@OptIn(ExperimentalComposeUiApi::class)
+fun Modifier.rotaryHandler(
+ rotaryScrollHandler: RotaryScrollHandler,
+ // TODO: batching causes additional delays. Return once it's clear that
+ // we will use it
+ /* batchTimeframe: Long = 0L,*/
+ reverseDirection: Boolean,
+ rotaryHaptics: RotaryHapticHandler,
+): Modifier = composed {
+ val channel = rememberTimestampChannel()
+ val eventsFlow = remember(channel) { channel.receiveAsFlow() }
+
+ composed {
+ LaunchedEffect(eventsFlow) {
+ eventsFlow
+ // TODO: batching causes additional delays. Return once it's clear that
+ // we will use it
+ // Do we really need to do this on this level?
+ // .batchRequestsWithinTimeframe(batchTimeframe)
+ .collectLatest {
+ debugLog {
+ "Scroll event received: " + "delta:${it.delta}, timestamp:${it.timestamp}"
+ }
+ rotaryScrollHandler.handleScrollEvent(this, it, rotaryHaptics)
+ }
+ }
+ this.onRotaryScrollEvent {
+ // Okay to ignore the ChannelResult returned from trySend because it is conflated
+ // (see rememberTimestampChannel()).
+ @Suppress("UNUSED_VARIABLE")
+ val unused =
+ channel.trySend(
+ TimestampedDelta(
+ it.uptimeMillis,
+ it.verticalScrollPixels * if (reverseDirection) -1f else 1f,
+ ),
+ )
+ true
+ }
+ }
+}
+
+/**
+ * Batching requests for scrolling events. This function combines all events together (except first)
+ * within specified timeframe. Should help with performance on high-res devices.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+fun Flow<TimestampedDelta>.batchRequestsWithinTimeframe(timeframe: Long): Flow<TimestampedDelta> {
+ var delta = 0f
+ var lastTimestamp = -timeframe
+ return if (timeframe == 0L) {
+ this
+ } else {
+ this.transformLatest {
+ delta += it.delta
+ debugLog { "Batching requests. delta:$delta" }
+ if (lastTimestamp + timeframe <= it.timestamp) {
+ lastTimestamp = it.timestamp
+ debugLog { "No events before, delta= $delta" }
+ emit(TimestampedDelta(it.timestamp, delta))
+ } else {
+ delay(timeframe)
+ debugLog { "After delay, delta= $delta" }
+ if (delta > 0f) {
+ emit(TimestampedDelta(it.timestamp, delta))
+ }
+ }
+ delta = 0f
+ }
+ }
+}
+
+/**
+ * A scroll handler for RSB(high-res) without snapping and with or without fling A list is scrolled
+ * by the number of pixels received from the rotary device.
+ *
+ * This class is a little bit different from LowResScrollHandler class - it has a filtering for
+ * events which are coming with wrong sign ( this happens to rsb devices, especially at the end of
+ * the scroll)
+ *
+ * This scroll handler supports fling. It can be set with [RotaryFlingBehavior].
+ */
+internal class HighResRotaryScrollHandler(
+ private val rotaryFlingBehaviorFactory: () -> RotaryFlingBehavior?,
+ private val scrollBehaviorFactory: () -> RotaryScrollBehavior,
+ private val hapticsThreshold: Long = 50,
+) : RotaryScrollHandler {
+
+ // This constant is specific for high-res devices. Because that input values
+ // can sometimes come with different sign, we have to filter them in this threshold
+ private val gestureThresholdTime = 200L
+ private var scrollJob: Job = CompletableDeferred<Unit>()
+ private var flingJob: Job = CompletableDeferred<Unit>()
+
+ private var previousScrollEventTime = 0L
+ private var rotaryScrollDistance = 0f
+
+ private var rotaryFlingBehavior: RotaryFlingBehavior? = rotaryFlingBehaviorFactory()
+ private var scrollBehavior: RotaryScrollBehavior = scrollBehaviorFactory()
+
+ override suspend fun handleScrollEvent(
+ coroutineScope: CoroutineScope,
+ event: TimestampedDelta,
+ rotaryHaptics: RotaryHapticHandler,
+ ) {
+ val time = event.timestamp
+ val isOppositeScrollValue = isOppositeValueAfterScroll(event.delta)
+
+ if (isNewScrollEvent(time)) {
+ debugLog { "New scroll event" }
+ resetTracking(time)
+ rotaryScrollDistance = event.delta
+ } else {
+ // Due to the physics of Rotary side button, some events might come
+ // with an opposite axis value - either at the start or at the end of the motion.
+ // We don't want to use these values for fling calculations.
+ if (!isOppositeScrollValue) {
+ rotaryFlingBehavior?.observeEvent(event.timestamp, event.delta)
+ } else {
+ debugLog { "Opposite value after scroll :${event.delta}" }
+ }
+ rotaryScrollDistance += event.delta
+ }
+
+ scrollJob.cancel()
+
+ rotaryHaptics.handleScrollHaptic(event.delta)
+ debugLog { "Rotary scroll distance: $rotaryScrollDistance" }
+
+ previousScrollEventTime = time
+ scrollJob = coroutineScope.async { scrollBehavior.handleEvent(rotaryScrollDistance) }
+
+ if (rotaryFlingBehavior != null) {
+ flingJob.cancel()
+ flingJob =
+ coroutineScope.async {
+ rotaryFlingBehavior?.trackFling(
+ beforeFling = {
+ debugLog { "Calling before fling section" }
+ scrollJob.cancel()
+ scrollBehavior = scrollBehaviorFactory()
+ }
+ )
+ }
+ }
+ }
+
+ private fun isOppositeValueAfterScroll(delta: Float): Boolean =
+ sign(rotaryScrollDistance) * sign(delta) == -1f && (abs(delta) < abs(rotaryScrollDistance))
+
+ private fun isNewScrollEvent(timestamp: Long): Boolean {
+ val timeDelta = timestamp - previousScrollEventTime
+ return previousScrollEventTime == 0L || timeDelta > gestureThresholdTime
+ }
+
+ private fun resetTracking(timestamp: Long) {
+ scrollBehavior = scrollBehaviorFactory()
+ rotaryFlingBehavior = rotaryFlingBehaviorFactory()
+ rotaryFlingBehavior?.startFlingTracking(timestamp)
+ }
+}
+
+/**
+ * A scroll handler for Bezel(low-res) without snapping. This scroll handler supports fling. It can
+ * be set with RotaryFlingBehavior.
+ */
+internal class LowResRotaryScrollHandler(
+ private val rotaryFlingBehaviorFactory: () -> RotaryFlingBehavior?,
+ private val scrollBehaviorFactory: () -> RotaryScrollBehavior,
+) : RotaryScrollHandler {
+
+ private val gestureThresholdTime = 200L
+ private var previousScrollEventTime = 0L
+ private var rotaryScrollDistance = 0f
+
+ private var scrollJob: Job = CompletableDeferred<Unit>()
+ private var flingJob: Job = CompletableDeferred<Unit>()
+
+ private var rotaryFlingBehavior: RotaryFlingBehavior? = rotaryFlingBehaviorFactory()
+ private var scrollBehavior: RotaryScrollBehavior = scrollBehaviorFactory()
+
+ override suspend fun handleScrollEvent(
+ coroutineScope: CoroutineScope,
+ event: TimestampedDelta,
+ rotaryHaptics: RotaryHapticHandler,
+ ) {
+ val time = event.timestamp
+
+ if (isNewScrollEvent(time)) {
+ resetTracking(time)
+ rotaryScrollDistance = event.delta
+ } else {
+ rotaryFlingBehavior?.observeEvent(event.timestamp, event.delta)
+ rotaryScrollDistance += event.delta
+ }
+
+ scrollJob.cancel()
+ flingJob.cancel()
+
+ rotaryHaptics.handleScrollHaptic(event.delta)
+ debugLog { "Rotary scroll distance: $rotaryScrollDistance" }
+
+ previousScrollEventTime = time
+ scrollJob = coroutineScope.async { scrollBehavior.handleEvent(rotaryScrollDistance) }
+
+ flingJob =
+ coroutineScope.async {
+ rotaryFlingBehavior?.trackFling(
+ beforeFling = {
+ debugLog { "Calling before fling section" }
+ scrollJob.cancel()
+ scrollBehavior = scrollBehaviorFactory()
+ },
+ )
+ }
+ }
+
+ private fun isNewScrollEvent(timestamp: Long): Boolean {
+ val timeDelta = timestamp - previousScrollEventTime
+ return previousScrollEventTime == 0L || timeDelta > gestureThresholdTime
+ }
+
+ private fun resetTracking(timestamp: Long) {
+ scrollBehavior = scrollBehaviorFactory()
+ debugLog { "Velocity tracker reset" }
+ rotaryFlingBehavior = rotaryFlingBehaviorFactory()
+ rotaryFlingBehavior?.startFlingTracking(timestamp)
+ }
+}
+
+/**
+ * A scroll handler for RSB(high-res) with snapping and without fling Snapping happens after a
+ * threshold is reached ( set in [RotarySnapBehavior])
+ *
+ * This scroll handler doesn't support fling.
+ */
+internal class HighResSnapHandler(
+ private val resistanceFactor: Float,
+ private val thresholdBehaviorFactory: () -> ThresholdBehavior,
+ private val snapBehaviourFactory: () -> RotarySnapBehavior,
+ private val scrollBehaviourFactory: () -> RotaryScrollBehavior,
+) : RotaryScrollHandler {
+ private val gestureThresholdTime = 200L
+ private val snapDelay = 100L
+ private val maxSnapsPerEvent = 2
+
+ private var scrollJob: Job = CompletableDeferred<Unit>()
+ private var snapJob: Job = CompletableDeferred<Unit>()
+
+ private var previousScrollEventTime = 0L
+ private var snapAccumulator = 0f
+ private var rotaryScrollDistance = 0f
+ private var scrollInProgress = false
+
+ private var snapBehaviour = snapBehaviourFactory()
+ private var scrollBehaviour = scrollBehaviourFactory()
+ private var thresholdBehavior = thresholdBehaviorFactory()
+
+ private val scrollEasing: Easing = CubicBezierEasing(0.0f, 0.0f, 0.5f, 1.0f)
+
+ override suspend fun handleScrollEvent(
+ coroutineScope: CoroutineScope,
+ event: TimestampedDelta,
+ rotaryHaptics: RotaryHapticHandler,
+ ) {
+ val time = event.timestamp
+
+ if (isNewScrollEvent(time)) {
+ debugLog { "New scroll event" }
+ resetTracking()
+ snapJob.cancel()
+ snapBehaviour = snapBehaviourFactory()
+ scrollBehaviour = scrollBehaviourFactory()
+ thresholdBehavior = thresholdBehaviorFactory()
+ thresholdBehavior.startThresholdTracking(time)
+ snapAccumulator = 0f
+ rotaryScrollDistance = 0f
+ }
+
+ if (!isOppositeValueAfterScroll(event.delta)) {
+ thresholdBehavior.observeEvent(event.timestamp, event.delta)
+ } else {
+ debugLog { "Opposite value after scroll :${event.delta}" }
+ }
+
+ thresholdBehavior.applySmoothing()
+ val snapThreshold = thresholdBehavior.snapThreshold()
+
+ snapAccumulator += event.delta
+ if (!snapJob.isActive) {
+ val resistanceCoeff =
+ 1 - scrollEasing.transform(rotaryScrollDistance.absoluteValue / snapThreshold)
+ rotaryScrollDistance += event.delta * resistanceCoeff
+ }
+
+ debugLog { "Snap accumulator: $snapAccumulator" }
+ debugLog { "Rotary scroll distance: $rotaryScrollDistance" }
+
+ debugLog { "snapThreshold: $snapThreshold" }
+ previousScrollEventTime = time
+
+ if (abs(snapAccumulator) > snapThreshold) {
+ scrollInProgress = false
+ scrollBehaviour = scrollBehaviourFactory()
+ scrollJob.cancel()
+
+ val snapDistance =
+ (snapAccumulator / snapThreshold)
+ .toInt()
+ .coerceIn(-maxSnapsPerEvent..maxSnapsPerEvent)
+ snapAccumulator -= snapThreshold * snapDistance
+ val sequentialSnap = snapJob.isActive
+
+ debugLog {
+ "Snap threshold reached: snapDistance:$snapDistance, " +
+ "sequentialSnap: $sequentialSnap, " +
+ "snap accumulator remaining: $snapAccumulator"
+ }
+ if (
+ (!snapBehaviour.topEdgeReached() && snapDistance < 0) ||
+ (!snapBehaviour.bottomEdgeReached() && snapDistance > 0)
+ ) {
+ rotaryHaptics.handleSnapHaptic(event.delta)
+ }
+
+ snapBehaviour.prepareSnapForItems(snapDistance, sequentialSnap)
+ if (!snapJob.isActive) {
+ snapJob.cancel()
+ snapJob =
+ coroutineScope.async {
+ debugLog { "Snap started" }
+ try {
+ snapBehaviour.snapToTargetItem()
+ } finally {
+ debugLog { "Snap called finally" }
+ }
+ }
+ }
+ rotaryScrollDistance = 0f
+ } else {
+ if (!snapJob.isActive) {
+ scrollJob.cancel()
+ debugLog { "Scrolling for $rotaryScrollDistance/$resistanceFactor px" }
+ scrollJob =
+ coroutineScope.async {
+ scrollBehaviour.handleEvent(rotaryScrollDistance / resistanceFactor)
+ }
+ delay(snapDelay)
+ scrollInProgress = false
+ scrollBehaviour = scrollBehaviourFactory()
+ rotaryScrollDistance = 0f
+ snapAccumulator = 0f
+ snapBehaviour.prepareSnapForItems(0, false)
+
+ snapJob.cancel()
+ snapJob = coroutineScope.async { snapBehaviour.snapToClosestItem() }
+ }
+ }
+ }
+
+ private fun isOppositeValueAfterScroll(delta: Float): Boolean =
+ sign(rotaryScrollDistance) * sign(delta) == -1f && (abs(delta) < abs(rotaryScrollDistance))
+
+ private fun isNewScrollEvent(timestamp: Long): Boolean {
+ val timeDelta = timestamp - previousScrollEventTime
+ return previousScrollEventTime == 0L || timeDelta > gestureThresholdTime
+ }
+
+ private fun resetTracking() {
+ scrollInProgress = true
+ }
+}
+
+/**
+ * A scroll handler for RSB(high-res) with snapping and without fling Snapping happens after a
+ * threshold is reached ( set in [RotarySnapBehavior])
+ *
+ * This scroll handler doesn't support fling.
+ */
+internal class LowResSnapHandler(
+ private val snapBehaviourFactory: () -> RotarySnapBehavior,
+) : RotaryScrollHandler {
+ private val gestureThresholdTime = 200L
+
+ private var snapJob: Job = CompletableDeferred<Unit>()
+
+ private var previousScrollEventTime = 0L
+ private var snapAccumulator = 0f
+ private var scrollInProgress = false
+
+ private var snapBehaviour = snapBehaviourFactory()
+
+ override suspend fun handleScrollEvent(
+ coroutineScope: CoroutineScope,
+ event: TimestampedDelta,
+ rotaryHaptics: RotaryHapticHandler,
+ ) {
+ val time = event.timestamp
+
+ if (isNewScrollEvent(time)) {
+ debugLog { "New scroll event" }
+ resetTracking()
+ snapJob.cancel()
+ snapBehaviour = snapBehaviourFactory()
+ snapAccumulator = 0f
+ }
+
+ snapAccumulator += event.delta
+
+ debugLog { "Snap accumulator: $snapAccumulator" }
+
+ previousScrollEventTime = time
+
+ if (abs(snapAccumulator) > 1f) {
+ scrollInProgress = false
+
+ val snapDistance = sign(snapAccumulator).toInt()
+ rotaryHaptics.handleSnapHaptic(event.delta)
+ val sequentialSnap = snapJob.isActive
+ debugLog {
+ "Snap threshold reached: snapDistance:$snapDistance, " +
+ "sequentialSnap: $sequentialSnap, " +
+ "snap accumulator: $snapAccumulator"
+ }
+
+ snapBehaviour.prepareSnapForItems(snapDistance, sequentialSnap)
+ if (!snapJob.isActive) {
+ snapJob.cancel()
+ snapJob =
+ coroutineScope.async {
+ debugLog { "Snap started" }
+ try {
+ snapBehaviour.snapToTargetItem()
+ } finally {
+ debugLog { "Snap called finally" }
+ }
+ }
+ }
+ snapAccumulator = 0f
+ }
+ }
+
+ private fun isNewScrollEvent(timestamp: Long): Boolean {
+ val timeDelta = timestamp - previousScrollEventTime
+ return previousScrollEventTime == 0L || timeDelta > gestureThresholdTime
+ }
+
+ private fun resetTracking() {
+ scrollInProgress = true
+ }
+}
+
+internal class ThresholdBehavior(
+ private val rotaryScrollAdapter: RotaryScrollAdapter,
+ private val thresholdDivider: Float,
+ private val minVelocity: Float = 300f,
+ private val maxVelocity: Float = 3000f,
+ private val smoothingConstant: Float = 0.4f,
+) {
+ private val thresholdDividerEasing: Easing = CubicBezierEasing(0.5f, 0.0f, 0.5f, 1.0f)
+
+ private val rotaryVelocityTracker = RotaryVelocityTracker()
+
+ private var smoothedVelocity = 0f
+ fun startThresholdTracking(time: Long) {
+ rotaryVelocityTracker.start(time)
+ smoothedVelocity = 0f
+ }
+
+ fun observeEvent(timestamp: Long, delta: Float) {
+ rotaryVelocityTracker.move(timestamp, delta)
+ }
+
+ fun applySmoothing() {
+ if (rotaryVelocityTracker.velocity != 0.0f) {
+ // smooth the velocity
+ smoothedVelocity =
+ exponentialSmoothing(
+ currentVelocity = rotaryVelocityTracker.velocity.absoluteValue,
+ prevVelocity = smoothedVelocity,
+ smoothingConstant = smoothingConstant,
+ )
+ }
+ debugLog { "rotaryVelocityTracker velocity: ${rotaryVelocityTracker.velocity}" }
+ debugLog { "SmoothedVelocity: $smoothedVelocity" }
+ }
+
+ fun snapThreshold(): Float {
+ val thresholdDividerFraction =
+ thresholdDividerEasing.transform(
+ inverseLerp(
+ minVelocity,
+ maxVelocity,
+ smoothedVelocity,
+ ),
+ )
+ return rotaryScrollAdapter.averageItemSize() /
+ lerp(
+ 1f,
+ thresholdDivider,
+ thresholdDividerFraction,
+ )
+ }
+
+ private fun exponentialSmoothing(
+ currentVelocity: Float,
+ prevVelocity: Float,
+ smoothingConstant: Float,
+ ): Float = smoothingConstant * currentVelocity + (1 - smoothingConstant) * prevVelocity
+}
+
+@Composable
+private fun rememberTimestampChannel() = remember {
+ Channel<TimestampedDelta>(capacity = Channel.CONFLATED)
+}
+
+private fun inverseLerp(start: Float, stop: Float, value: Float): Float {
+ return ((value - start) / (stop - start)).coerceIn(0f, 1f)
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/RotaryVelocityTracker.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/RotaryVelocityTracker.kt
new file mode 100644
index 000000000..1719ecef3
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/rotaryinput/RotaryVelocityTracker.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.rotaryinput
+
+import androidx.compose.ui.input.pointer.util.VelocityTracker1D
+
+// This file is a copy of RotaryVelocityTracker.kt from Horologist (go/horologist),
+// remove it once Wear Compose 1.4 is landed (b/325560444).
+
+/** A wrapper around VelocityTracker1D to provide support for rotary input. */
+class RotaryVelocityTracker {
+ private var velocityTracker: VelocityTracker1D = VelocityTracker1D(true)
+
+ /** Retrieve the last computed velocity. */
+ val velocity: Float
+ get() = velocityTracker.calculateVelocity()
+
+ /** Start tracking motion. */
+ fun start(currentTime: Long) {
+ velocityTracker.resetTracking()
+ velocityTracker.addDataPoint(currentTime, 0f)
+ }
+
+ /** Continue tracking motion as the input rotates. */
+ fun move(currentTime: Long, delta: Float) {
+ velocityTracker.addDataPoint(currentTime, delta)
+ }
+
+ /** Stop tracking motion. */
+ fun end() {
+ velocityTracker.resetTracking()
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
index 2719b9766..ba5ba1c23 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/MultiDeviceUtils.kt
@@ -27,7 +27,7 @@ object MultiDeviceUtils {
@JvmStatic
@ChecksSdkIntAtLeast(Build.VERSION_CODES.VANILLA_ICE_CREAM)
fun isDeviceAwareGrantFlowEnabled(): Boolean {
- return SdkLevel.isAtLeastV() && Flags.deviceAwarePermissionGrant()
+ return SdkLevel.isAtLeastV() && Flags.deviceAwarePermissionGrantEnabled()
}
@JvmStatic
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/CheckableLinearLayout.java b/PermissionController/src/com/android/permissioncontroller/role/ui/CheckableLinearLayout.java
index b396c3b7b..32a0bb20b 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/CheckableLinearLayout.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/CheckableLinearLayout.java
@@ -100,12 +100,10 @@ public class CheckableLinearLayout extends LinearLayout implements Checkable {
int count = viewGroup.getChildCount();
for (int i = 0; i < count; i++) {
View child = viewGroup.getChildAt(i);
- if (child.isDuplicateParentStateEnabled()) {
- if (child instanceof Checkable) {
- ((Checkable) child).setChecked(checked);
- } else if (child instanceof ViewGroup) {
- updateChildrenChecked((ViewGroup) child, checked);
- }
+ if (child instanceof Checkable) {
+ ((Checkable) child).setChecked(checked);
+ } else if (child instanceof ViewGroup) {
+ updateChildrenChecked((ViewGroup) child, checked);
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
index a8b16c521..145031b63 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
@@ -214,6 +214,8 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat
preference.setChecked(checked);
if (applicationInfo != null) {
+ roleApplicationPreference.setRestrictionIntent(
+ mRole.getApplicationRestrictionIntentAsUser(applicationInfo, mUser, context));
RoleUiBehaviorUtils.prepareApplicationPreferenceAsUser(mRole, roleApplicationPreference,
applicationInfo, mUser, context);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
index e68fa88a0..a1c4d84a5 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
@@ -182,6 +182,7 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat
preference = rolePreference.asPreference();
}
+ rolePreference.setRestrictionIntent(role.getRestrictionIntentAsUser(user, context));
List<ApplicationInfo> holderApplicationInfos = roleItem.getHolderApplicationInfos();
if (holderApplicationInfos.isEmpty()) {
preference.setIcon(null);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
index 80834a3e2..d9b4a9c44 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
@@ -35,7 +35,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
-import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
@@ -54,6 +53,7 @@ import com.android.permissioncontroller.permission.utils.PackageRemovalMonitor;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.role.model.UserDeniedManager;
import com.android.permissioncontroller.role.utils.PackageUtils;
+import com.android.permissioncontroller.role.utils.UiUtils;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
@@ -154,7 +154,6 @@ public class RequestRoleFragment extends DialogFragment {
View viewLayout = inflater.inflate(R.layout.request_role_view, null);
mListView = viewLayout.requireViewById(R.id.list);
- mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
mListView.setOnItemClickListener((parent, view, position, id) -> onItemClicked(position));
mAdapter = new Adapter(mListView, mRole);
if (savedInstanceState != null) {
@@ -414,9 +413,9 @@ public class RequestRoleFragment extends DialogFragment {
// Skip the "None" item.
continue;
}
- ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first;
- if (Objects.equals(qualifyingApplicationInfo.packageName, packageName)) {
- return qualifyingApplicationInfo.uid;
+ ApplicationInfo applicationInfo = qualifyingApplication.first;
+ if (Objects.equals(applicationInfo.packageName, packageName)) {
+ return applicationInfo.uid;
}
}
return -1;
@@ -439,19 +438,7 @@ public class RequestRoleFragment extends DialogFragment {
if (mAdapter == null) {
return null;
}
- int count = mAdapter.getCount();
- for (int i = 0; i < count; i++) {
- Pair<ApplicationInfo, Boolean> qualifyingApplication = mAdapter.getItem(i);
- if (qualifyingApplication == null) {
- // Skip the "None" item.
- continue;
- }
- boolean isHolderApplication = qualifyingApplication.second;
- if (isHolderApplication) {
- return qualifyingApplication.first.packageName;
- }
- }
- return null;
+ return mAdapter.mHolderPackageName;
}
static void reportRequestResult(int requestingUid, String requestingPackageName,
@@ -477,8 +464,8 @@ public class RequestRoleFragment extends DialogFragment {
private static final String STATE_USER_CHECKED = Adapter.class.getName()
+ ".state.USER_CHECKED";
- private static final String STATE_USER_CHECKED_PACKAGE_NAME = Adapter.class.getName()
- + ".state.USER_CHECKED_PACKAGE_NAME";
+ private static final String STATE_CHECKED_PACKAGE_NAME = Adapter.class.getName()
+ + ".state.CHECKED_PACKAGE_NAME";
private static final int LAYOUT_TRANSITION_DURATION_MILLIS = 150;
@@ -493,7 +480,8 @@ public class RequestRoleFragment extends DialogFragment {
private final List<Pair<ApplicationInfo, Boolean>> mQualifyingApplications =
new ArrayList<>();
- private boolean mHasHolderApplication;
+ @Nullable
+ private String mHolderPackageName;
private boolean mDontAskAgain;
@@ -501,10 +489,8 @@ public class RequestRoleFragment extends DialogFragment {
// the current holder as checked.
private boolean mUserChecked;
- private boolean mPendingUserChecked;
- // We may use a null to represent the "None" item.
@Nullable
- private String mPendingUserCheckedPackageName;
+ private String mCheckedPackageName;
Adapter(@NonNull ListView listView, @NonNull Role role) {
mListView = listView;
@@ -514,15 +500,14 @@ public class RequestRoleFragment extends DialogFragment {
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(STATE_USER_CHECKED, mUserChecked);
if (mUserChecked) {
- outState.putString(STATE_USER_CHECKED_PACKAGE_NAME, getCheckedPackageName());
+ outState.putString(STATE_CHECKED_PACKAGE_NAME, mCheckedPackageName);
}
}
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
- mPendingUserChecked = savedInstanceState.getBoolean(STATE_USER_CHECKED);
- if (mPendingUserChecked) {
- mPendingUserCheckedPackageName = savedInstanceState.getString(
- STATE_USER_CHECKED_PACKAGE_NAME);
+ mUserChecked = savedInstanceState.getBoolean(STATE_USER_CHECKED);
+ if (mUserChecked) {
+ mCheckedPackageName = savedInstanceState.getString(STATE_CHECKED_PACKAGE_NAME);
}
}
@@ -533,14 +518,28 @@ public class RequestRoleFragment extends DialogFragment {
mDontAskAgain = dontAskAgain;
if (mDontAskAgain) {
mUserChecked = false;
- updateItemChecked();
+ mCheckedPackageName = mHolderPackageName;
}
notifyDataSetChanged();
}
public void onItemClicked(int position) {
- mUserChecked = true;
- // We may need to change description based on checked state.
+ Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position);
+ if (qualifyingApplication == null) {
+ mUserChecked = true;
+ mCheckedPackageName = null;
+ } else {
+ ApplicationInfo applicationInfo = qualifyingApplication.first;
+ Intent restrictionIntent = mRole.getApplicationRestrictionIntentAsUser(
+ applicationInfo, Process.myUserHandle(), mListView.getContext());
+ if (restrictionIntent != null) {
+ mListView.getContext().startActivity(restrictionIntent);
+ return;
+ } else {
+ mUserChecked = true;
+ mCheckedPackageName = applicationInfo.packageName;
+ }
+ }
notifyDataSetChanged();
}
@@ -550,42 +549,10 @@ public class RequestRoleFragment extends DialogFragment {
mQualifyingApplications.add(0, null);
}
mQualifyingApplications.addAll(qualifyingApplications);
- mHasHolderApplication = hasHolderApplication(qualifyingApplications);
- notifyDataSetChanged();
-
- if (mPendingUserChecked) {
- restoreItemChecked();
- mPendingUserChecked = false;
- mPendingUserCheckedPackageName = null;
- }
-
- if (!mUserChecked) {
- updateItemChecked();
- }
- }
-
- private static boolean hasHolderApplication(
- @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) {
- int qualifyingApplicationsSize = qualifyingApplications.size();
- for (int i = 0; i < qualifyingApplicationsSize; i++) {
- Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(
- i);
- boolean isHolderApplication = qualifyingApplication.second;
-
- if (isHolderApplication) {
- return true;
- }
- }
- return false;
- }
+ mHolderPackageName = getHolderPackageName(qualifyingApplications);
- private void restoreItemChecked() {
- if (mPendingUserCheckedPackageName == null) {
- if (mRole.shouldShowNone()) {
- mUserChecked = true;
- mListView.setItemChecked(0, true);
- }
- } else {
+ if (mUserChecked && mCheckedPackageName != null) {
+ boolean isCheckedPackageNameFound = false;
int count = getCount();
for (int i = 0; i < count; i++) {
Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(i);
@@ -594,55 +561,52 @@ public class RequestRoleFragment extends DialogFragment {
}
String packageName = qualifyingApplication.first.packageName;
- if (Objects.equals(packageName, mPendingUserCheckedPackageName)) {
+ if (Objects.equals(packageName, mCheckedPackageName)) {
mUserChecked = true;
- mListView.setItemChecked(i, true);
+ isCheckedPackageNameFound = true;
break;
}
}
+ if (!isCheckedPackageNameFound) {
+ mUserChecked = false;
+ mCheckedPackageName = null;
+ }
}
+
+ if (!mUserChecked) {
+ mCheckedPackageName = mHolderPackageName;
+ }
+
+ notifyDataSetChanged();
}
- private void updateItemChecked() {
- if (!mHasHolderApplication) {
- if (mRole.shouldShowNone()) {
- mListView.setItemChecked(0, true);
- } else {
- mListView.clearChoices();
+ @Nullable
+ private static String getHolderPackageName(
+ @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) {
+ int qualifyingApplicationSize = qualifyingApplications.size();
+ for (int i = 0; i < qualifyingApplicationSize; i++) {
+ Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(
+ i);
+ if (qualifyingApplication == null) {
+ continue;
}
- } else {
- int count = getCount();
- for (int i = 0; i < count; i++) {
- Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(i);
- if (qualifyingApplication == null) {
- continue;
- }
- boolean isHolderApplication = qualifyingApplication.second;
+ ApplicationInfo applicationInfo = qualifyingApplication.first;
+ boolean isHolderApplication = qualifyingApplication.second;
- if (isHolderApplication) {
- mListView.setItemChecked(i, true);
- break;
- }
+ if (isHolderApplication) {
+ return applicationInfo.packageName;
}
}
- }
-
- @Nullable
- public Pair<ApplicationInfo, Boolean> getCheckedItem() {
- int position = mListView.getCheckedItemPosition();
- return position != AdapterView.INVALID_POSITION ? getItem(position) : null;
+ return null;
}
@Nullable
public String getCheckedPackageName() {
- Pair<ApplicationInfo, Boolean> qualifyingApplication = getCheckedItem();
- return qualifyingApplication == null ? null : qualifyingApplication.first.packageName;
+ return mCheckedPackageName;
}
public boolean isHolderApplicationChecked() {
- Pair<ApplicationInfo, Boolean> qualifyingApplication = getCheckedItem();
- return qualifyingApplication == null ? !mHasHolderApplication
- : qualifyingApplication.second;
+ return Objects.equals(mCheckedPackageName, mHolderPackageName);
}
@Override
@@ -684,7 +648,7 @@ public class RequestRoleFragment extends DialogFragment {
}
Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position);
if (qualifyingApplication == null) {
- return !mHasHolderApplication;
+ return mHolderPackageName == null;
} else {
boolean isHolderApplication = qualifyingApplication.second;
return isHolderApplication;
@@ -695,13 +659,13 @@ public class RequestRoleFragment extends DialogFragment {
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
Context context = parent.getContext();
- View view = convertView;
+ CheckableLinearLayout view = (CheckableLinearLayout) convertView;
ViewHolder holder;
if (view != null) {
holder = (ViewHolder) view.getTag();
} else {
- view = LayoutInflater.from(context).inflate(R.layout.request_role_item, parent,
- false);
+ view = (CheckableLinearLayout) LayoutInflater.from(context).inflate(
+ R.layout.request_role_item, parent, false);
holder = new ViewHolder(view);
view.setTag(holder);
@@ -709,28 +673,36 @@ public class RequestRoleFragment extends DialogFragment {
LAYOUT_TRANSITION_DURATION_MILLIS);
}
- view.setEnabled(isEnabled(position));
-
Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position);
+ boolean restricted;
+ boolean checked;
Drawable icon;
String title;
String subtitle;
if (qualifyingApplication == null) {
+ restricted = false;
+ checked = mCheckedPackageName == null;
icon = AppCompatResources.getDrawable(context, R.drawable.ic_remove_circle);
title = context.getString(R.string.default_app_none);
- subtitle = !mHasHolderApplication ? context.getString(
+ subtitle = mHolderPackageName != null ? context.getString(
R.string.request_role_current_default) : null;
} else {
- ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first;
- icon = Utils.getBadgedIcon(context, qualifyingApplicationInfo);
- title = Utils.getAppLabel(qualifyingApplicationInfo, context);
+ ApplicationInfo applicationInfo = qualifyingApplication.first;
+ restricted = mRole.getApplicationRestrictionIntentAsUser(applicationInfo,
+ Process.myUserHandle(), context) != null;
+ checked = Objects.equals(applicationInfo.packageName, mCheckedPackageName);
+ icon = Utils.getBadgedIcon(context, applicationInfo);
+ title = Utils.getAppLabel(applicationInfo, context);
boolean isHolderApplication = qualifyingApplication.second;
subtitle = isHolderApplication
? context.getString(R.string.request_role_current_default)
- : mListView.isItemChecked(position)
- ? context.getString(mRole.getRequestDescriptionResource()) : null;
+ : checked ? context.getString(mRole.getRequestDescriptionResource()) : null;
}
+ boolean enabled = isEnabled(position);
+ UiUtils.setViewTreeEnabled(view, enabled && !restricted);
+ view.setEnabled(enabled);
+ view.setChecked(checked);
holder.iconImage.setImageDrawable(icon);
holder.titleText.setText(title);
holder.subtitleText.setVisibility(!TextUtils.isEmpty(subtitle) ? View.VISIBLE
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreference.java
index 71b0ef98b..f68253161 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreference.java
@@ -16,9 +16,8 @@
package com.android.permissioncontroller.role.ui;
-import android.os.UserHandle;
+import android.content.Intent;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
@@ -27,13 +26,7 @@ import androidx.annotation.Nullable;
public interface RestrictionAwarePreference {
/**
- * Specifies user restriction that blocks this preference.
+ * Set the restriction intent that blocks this preference.
*/
- void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user);
-
- /**
- * Specifies enhanced confirmation restrictions that block this preference.
- */
- void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user);
+ void setRestrictionIntent(@Nullable Intent restrictionIntent);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreferenceMixin.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreferenceMixin.java
index b5177834c..8d757324f 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreferenceMixin.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RestrictionAwarePreferenceMixin.java
@@ -16,25 +16,13 @@
package com.android.permissioncontroller.role.ui;
-import android.app.admin.DevicePolicyManager;
-import android.app.ecm.EnhancedConfirmationManager;
-import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
-import com.android.modules.utils.build.SdkLevel;
-import com.android.permissioncontroller.DeviceUtils;
-import com.android.permissioncontroller.role.utils.UserUtils;
-
/**
* Mixin for implementing {@link RestrictionAwarePreference}.
*/
@@ -46,96 +34,35 @@ public class RestrictionAwarePreferenceMixin {
private final Preference mPreference;
@Nullable
- private String mUserRestriction;
-
- @Nullable
- private String mEnhancedConfirmationRestrictedPackageName;
- @Nullable
- private String mEnhancedConfirmationRestrictedSettingIdentifier;
-
- @Nullable
- private UserHandle mUser;
+ private Intent mRestrictionIntent;
public RestrictionAwarePreferenceMixin(@NonNull Preference preference) {
mPreference = preference;
}
/**
- * Implementation for {@link RestrictionAwarePreference#setUserRestriction}.
+ * Implementation for {@link RestrictionAwarePreference#setRestrictionIntent}.
*/
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mUserRestriction = userRestriction;
- mUser = user;
- updateEnabled();
- }
-
- /**
- * Implementation for {@link RestrictionAwarePreference#setEnhancedConfirmationRestriction}.
- */
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- if (!isEnhancedConfirmationRestrictionEnabled()) {
- return;
- }
- mEnhancedConfirmationRestrictedPackageName = packageName;
- mEnhancedConfirmationRestrictedSettingIdentifier = settingIdentifier;
- mUser = user;
- updateEnabled();
- }
-
- private boolean isEnhancedConfirmationRestrictionEnabled() {
- // Enhanced confirmation restriction is currently applied only to handheld.
- Context context = mPreference.getContext();
- return !(DeviceUtils.isAuto(context) || DeviceUtils.isTelevision(context)
- || DeviceUtils.isWear(context));
- }
-
- private void updateEnabled() {
- mPreference.setEnabled(mUserRestriction == null
- && (mEnhancedConfirmationRestrictedPackageName == null
- || mEnhancedConfirmationRestrictedSettingIdentifier == null));
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionIntent = restrictionIntent;
+ mPreference.setEnabled(mRestrictionIntent == null);
}
/**
* Call after {@link Preference#onBindViewHolder} to apply blocking effects.
*/
public void onAfterBindViewHolder(@NonNull PreferenceViewHolder holder) {
- View.OnClickListener onClickListener = null;
- if (SdkLevel.isAtLeastV()
- && mEnhancedConfirmationRestrictedPackageName != null
- && mEnhancedConfirmationRestrictedSettingIdentifier != null
- && mUser != null) {
- Context context = UserUtils.getUserContext(holder.itemView.getContext(), mUser);
- onClickListener = (view) -> {
- EnhancedConfirmationManager enhancedConfirmationManager =
- context.getSystemService(EnhancedConfirmationManager.class);
- try {
- context.startActivity(
- enhancedConfirmationManager.createRestrictedSettingDialogIntent(
- mEnhancedConfirmationRestrictedPackageName,
- mEnhancedConfirmationRestrictedSettingIdentifier));
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Package name is not found.", e);
- }
- };
- } else if (mUserRestriction != null) {
- Intent userRestrictionIntent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS)
- .putExtra(DevicePolicyManager.EXTRA_RESTRICTION, mUserRestriction);
- onClickListener = (view) -> {
- holder.itemView.getContext().startActivity(userRestrictionIntent);
- };
- }
-
- // We set the item view to enabled to make the preference row clickable.
- // Normal disabled preferences have the whole view hierarchy disabled, so by making only
- // the top-level itemView enabled, we don't change the fact that the whole preference
- // still "looks" disabled (see Preference.onBindViewHolder).
- // Preference.onBindViewHolder sets the onClickListener as well on each preference, so
- // we don't need to unset the listener here (we wouldn't know the correct one anyway).
- // This approach is used already by com.android.settingslib.RestrictedPreferenceHelper.
- if (onClickListener != null) {
+ if (mRestrictionIntent != null) {
+ // We set the item view to enabled to make the preference row clickable.
+ // Normal disabled preferences have the whole view hierarchy disabled, so by making only
+ // the top-level itemView enabled, we don't change the fact that the whole preference
+ // still "looks" disabled (see Preference.onBindViewHolder).
+ // Preference.onBindViewHolder sets the onClickListener as well on each preference, so
+ // we don't need to unset the listener here (we wouldn't know the correct one anyway).
+ // This approach is used already by com.android.settingslib.RestrictedPreferenceHelper.
holder.itemView.setEnabled(true);
- holder.itemView.setOnClickListener(onClickListener);
+ holder.itemView.setOnClickListener(
+ view -> view.getContext().startActivity(mRestrictionIntent));
}
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
index becbbea62..bbc123cfe 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
@@ -16,6 +16,7 @@
package com.android.permissioncontroller.role.ui;
+import androidx.annotation.NonNull;
import androidx.preference.Preference;
/**
@@ -25,5 +26,6 @@ public interface RolePreference extends TwoTargetPreference, RestrictionAwarePre
/**
* Return this preference as {@link Preference}.
*/
+ @NonNull
Preference asPreference();
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/TwoTargetPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/TwoTargetPreference.java
index 3a8cd55d3..ab2387686 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/TwoTargetPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/TwoTargetPreference.java
@@ -41,6 +41,7 @@ public interface TwoTargetPreference {
/**
* Return this preference as {@link Preference}.
*/
+ @NonNull
Preference asPreference();
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
index ebeba0482..764c07497 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
@@ -17,7 +17,7 @@
package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.widget.RadioButton;
import androidx.annotation.NonNull;
@@ -37,7 +37,7 @@ public class AutoRadioPreference extends TwoStatePreference implements
private final RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
- public AutoRadioPreference(Context context) {
+ public AutoRadioPreference(@NonNull Context context) {
super(context, null,
TypedArrayUtils.getAttr(context, androidx.preference.R.attr.preferenceStyle,
android.R.attr.preferenceStyle));
@@ -50,7 +50,7 @@ public class AutoRadioPreference extends TwoStatePreference implements
}
@Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
RadioButton radioButton = (RadioButton) holder.findViewById(R.id.radio_button);
@@ -60,17 +60,11 @@ public class AutoRadioPreference extends TwoStatePreference implements
}
@Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
- }
-
- @Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
+ @NonNull
@Override
public AutoRadioPreference asTwoStatePreference() {
return this;
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
index af4f0cc0a..15fd117d1 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
@@ -17,11 +17,13 @@
package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.util.AttributeSet;
+import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.StyleRes;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
@@ -39,12 +41,12 @@ public class AutoRolePreference extends Preference implements RolePreference {
new RestrictionAwarePreferenceMixin(this);
public AutoRolePreference(@NonNull Context context,
- @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public AutoRolePreference(@NonNull Context context, @Nullable AttributeSet attrs,
- int defStyleAttr) {
+ @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -57,28 +59,21 @@ public class AutoRolePreference extends Preference implements RolePreference {
}
@Override
- public void setOnSecondTargetClickListener(@Nullable OnSecondTargetClickListener listener) {
- }
-
- @Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
- }
+ public void setOnSecondTargetClickListener(@Nullable OnSecondTargetClickListener listener) {}
@Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
+ @NonNull
@Override
public AutoRolePreference asPreference() {
return this;
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
index a21bc8d8b..bfb2b5d1d 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
@@ -17,7 +17,7 @@
package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.util.AttributeSet;
import androidx.annotation.AttrRes;
@@ -58,19 +58,12 @@ public class AutoSwitchPreference extends SwitchPreference
}
@Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
index 4c7d636d7..67f04051c 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
@@ -17,7 +17,7 @@
package com.android.permissioncontroller.role.ui.handheld;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
@@ -56,19 +56,12 @@ public class HandheldRadioPreference extends SelectorWithWidgetPreference implem
}
@Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
index 270e3a928..3d09f0b46 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
@@ -17,7 +17,7 @@
package com.android.permissioncontroller.role.ui.handheld;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.util.AttributeSet;
import android.view.View;
@@ -94,15 +94,8 @@ public class HandheldRolePreference extends TwoTargetPreference implements RoleP
}
@Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
- }
-
- @Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@Override
@@ -124,6 +117,7 @@ public class HandheldRolePreference extends TwoTargetPreference implements RoleP
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
+ @NonNull
@Override
public HandheldRolePreference asPreference() {
return this;
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java
index b95440bbd..4b397343c 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java
@@ -164,6 +164,9 @@ public class SpecialAppAccessChildFragment<PF extends PreferenceFragmentCompat
preference.setChecked(isHolderPackage);
UserHandle user = UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid);
+ roleApplicationPreference.setRestrictionIntent(
+ mRole.getApplicationRestrictionIntentAsUser(qualifyingApplicationInfo, user,
+ context));
RoleUiBehaviorUtils.prepareApplicationPreferenceAsUser(mRole, roleApplicationPreference,
qualifyingApplicationInfo, user, context);
preferenceScreen.addPreference(preference);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
index b06904930..cacb4377f 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessListChildFragment.java
@@ -115,10 +115,11 @@ public class SpecialAppAccessListChildFragment<PF extends PreferenceFragmentComp
} else {
preference = rolePreference.asPreference();
}
+
+ rolePreference.setRestrictionIntent(role.getRestrictionIntentAsUser(
+ Process.myUserHandle(), context));
RoleUiBehaviorUtils.preparePreferenceAsUser(role, roleItem.getHolderApplicationInfos(),
- rolePreference,
- Process.myUserHandle(),
- context);
+ rolePreference, Process.myUserHandle(), context);
preferenceScreen.addPreference(preference);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
index d5081566d..ded6d5cb5 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
@@ -17,7 +17,7 @@
package com.android.permissioncontroller.role.ui.specialappaccess.handheld;
import android.content.Context;
-import android.os.UserHandle;
+import android.content.Intent;
import android.util.AttributeSet;
import androidx.annotation.AttrRes;
@@ -56,19 +56,12 @@ public class HandheldSwitchPreference extends AppSwitchPreference
}
@Override
- public void setUserRestriction(@Nullable String userRestriction, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setUserRestriction(userRestriction, user);
+ public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
+ mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@Override
- public void setEnhancedConfirmationRestriction(@Nullable String packageName,
- @Nullable String settingIdentifier, @NonNull UserHandle user) {
- mRestrictionAwarePreferenceMixin.setEnhancedConfirmationRestriction(packageName,
- settingIdentifier, user);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
index 430860bbb..abaa33a56 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
@@ -16,11 +16,8 @@
package com.android.permissioncontroller.role.ui.wear
-import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.Intent
-import android.os.UserHandle
-import android.provider.Settings
import androidx.preference.TwoStatePreference
import com.android.permissioncontroller.role.ui.RoleApplicationPreference
@@ -33,36 +30,15 @@ class WearRoleApplicationPreference(
val label: String,
val checked: Boolean,
val onDefaultCheckChanged: (Boolean) -> Unit = {},
- private var restriction: String? = null,
- private var user: UserHandle? = null
+ private var restrictionIntent: Intent? = 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
+ restrictionIntent?.let { { _ -> context.startActivity(it) } } ?: onDefaultCheckChanged
- override fun setUserRestriction(userRestriction: String?, userHandle: UserHandle) {
- restriction = userRestriction
- user = userHandle
- setEnabled(restriction == null)
+ override fun setRestrictionIntent(restrictionIntent: Intent?) {
+ this.restrictionIntent = restrictionIntent
+ setEnabled(restrictionIntent == null)
}
- override fun setEnhancedConfirmationRestriction(
- packageName: String?,
- settingIdentifier: String?,
- user: UserHandle
- ) {
- // no-op because Enhanced Confirmation Restriction is not applied to wear yet.
- return
- }
-
- override fun asTwoStatePreference(): TwoStatePreference {
- return this
- }
+ override fun asTwoStatePreference(): TwoStatePreference = this
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
index 9acaa158d..43acf4293 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
@@ -16,11 +16,8 @@
package com.android.permissioncontroller.role.ui.wear
-import android.app.admin.DevicePolicyManager
import android.content.Context
import android.content.Intent
-import android.os.UserHandle
-import android.provider.Settings
import androidx.preference.Preference
import com.android.permissioncontroller.role.ui.RolePreference
import com.android.permissioncontroller.role.ui.TwoTargetPreference.OnSecondTargetClickListener
@@ -31,41 +28,20 @@ class WearRolePreference(
context: Context,
val label: String,
val onDefaultClicked: () -> Unit = {},
- private var restriction: String? = null,
- private var user: UserHandle? = null
+ private var restrictionIntent: Intent? = null
) : TwoTargetPreference(context), RolePreference {
override fun setOnSecondTargetClickListener(listener: OnSecondTargetClickListener?) {
// no-op
}
- override fun setUserRestriction(userRestriction: String?, userHandle: UserHandle) {
- restriction = userRestriction
- user = userHandle
- setEnabled(restriction == null)
+ override fun setRestrictionIntent(restrictionIntent: Intent?) {
+ this.restrictionIntent = restrictionIntent
+ setEnabled(restrictionIntent == null)
}
- override fun setEnhancedConfirmationRestriction(
- packageName: String?,
- settingIdentifier: String?,
- user: UserHandle
- ) {
- // no-op because Enhanced Confirmation Restriction is not applied to wear yet.
- return
- }
-
- override fun asPreference(): Preference {
- return this
- }
+ override fun asPreference(): Preference = this
fun getOnClicked(): () -> Unit =
- restriction?.let {
- return {
- context.startActivity(
- Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS)
- .putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction)
- )
- }
- }
- ?: onDefaultClicked
+ restrictionIntent?.let { { context.startActivity(it) } } ?: onDefaultClicked
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
index 175bd71e5..21d16695c 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/utils/RoleUiBehaviorUtils.java
@@ -16,21 +16,15 @@
package com.android.permissioncontroller.role.utils;
-import android.app.ecm.EnhancedConfirmationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.permission.flags.Flags;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.modules.utils.build.SdkLevel;
-import com.android.permissioncontroller.role.ui.RestrictionAwarePreference;
import com.android.permissioncontroller.role.ui.RoleApplicationPreference;
import com.android.permissioncontroller.role.ui.RolePreference;
import com.android.permissioncontroller.role.ui.behavior.RoleUiBehavior;
@@ -85,8 +79,6 @@ public final class RoleUiBehaviorUtils {
public static void preparePreferenceAsUser(@NonNull Role role,
@NonNull List<ApplicationInfo> applicationInfos, @NonNull RolePreference preference,
@NonNull UserHandle user, @NonNull Context context) {
- prepareUserRestrictionAwarePreferenceAsUser(role, preference, user, context);
-
RoleUiBehavior uiBehavior = getUiBehavior(role);
if (uiBehavior == null) {
return;
@@ -101,9 +93,6 @@ public final class RoleUiBehaviorUtils {
@NonNull RoleApplicationPreference preference,
@NonNull ApplicationInfo applicationInfo, @NonNull UserHandle user,
@NonNull Context context) {
- prepareUserRestrictionAwarePreferenceAsUser(role, preference, user, context);
- prepareEnhancedConfirmationRestrictionAwarePreferenceAsUser(role, preference,
- applicationInfo.packageName, user, context);
RoleUiBehavior uiBehavior = getUiBehavior(role);
if (uiBehavior == null) {
return;
@@ -113,55 +102,6 @@ public final class RoleUiBehaviorUtils {
context);
}
- private static void prepareUserRestrictionAwarePreferenceAsUser(@NonNull Role role,
- @NonNull RestrictionAwarePreference preference, @NonNull UserHandle user,
- @NonNull Context context) {
- if (SdkLevel.isAtLeastU() && role.isExclusive()) {
- UserManager userManager = context.getSystemService(UserManager.class);
- boolean hasDisallowConfigDefaultApps = userManager.hasUserRestrictionForUser(
- UserManager.DISALLOW_CONFIG_DEFAULT_APPS, user);
- preference.setUserRestriction(hasDisallowConfigDefaultApps
- ? UserManager.DISALLOW_CONFIG_DEFAULT_APPS : null, user);
- }
- }
-
- private static void prepareEnhancedConfirmationRestrictionAwarePreferenceAsUser(
- @NonNull Role role, @NonNull RestrictionAwarePreference preference,
- @NonNull String packageName, @NonNull UserHandle user, @NonNull Context context) {
- if (isEnhancedConfirmationRestrictedAsUser(packageName, role.getName(), user, context)) {
- preference.setEnhancedConfirmationRestriction(packageName, role.getName(), user);
- } else {
- preference.setEnhancedConfirmationRestriction(null, null, user);
- }
- }
-
- /**
- * This method checks if the package is restricted from a specific role with the given user.
- *
- * @param packageName the package name to check for
- * @param user the user to check for
- * @param context the {@code Context} to retrieve system services
- *
- * @return whether the package is restricted for a role
- */
- private static boolean isEnhancedConfirmationRestrictedAsUser(@NonNull String packageName,
- @NonNull String roleName, @NonNull UserHandle user, @NonNull Context context) {
- if (SdkLevel.isAtLeastV()
- && Flags.enhancedConfirmationModeApisEnabled()) {
- Context userContext = UserUtils.getUserContext(context, user);
- EnhancedConfirmationManager enhancedConfirmationManager =
- userContext.getSystemService(EnhancedConfirmationManager.class);
- try {
- if (enhancedConfirmationManager.isRestricted(packageName, roleName)) {
- return true;
- }
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(LOG_TAG, "Cannot find package name:" + packageName, e);
- }
- }
- return false;
- }
-
/**
* @see RoleUiBehavior#getConfirmationMessage
*/
diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/UiUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/UiUtils.java
index e13e55c51..4d3320667 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/utils/UiUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/utils/UiUtils.java
@@ -18,16 +18,12 @@ package com.android.permissioncontroller.role.utils;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
import android.view.View;
+import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import androidx.annotation.Dimension;
import androidx.annotation.NonNull;
-import androidx.annotation.Px;
/**
* Utility methods about UI.
@@ -37,6 +33,26 @@ public class UiUtils {
private UiUtils() {}
/**
+ * Set enabled state on a view and its children recursively.
+ *
+ * @see androidx.preference.Preference#setEnabledStateOnViews
+ *
+ * @param view the view to be set to enabled or not
+ * @param enabled whether the view should be enabled
+ */
+ public static void setViewTreeEnabled(@NonNull View view, boolean enabled) {
+ view.setEnabled(enabled);
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ int childCount = viewGroup.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ View childView = viewGroup.getChildAt(i);
+ setViewTreeEnabled(childView, enabled);
+ }
+ }
+ }
+
+ /**
* Set whether a view is shown.
*
* @param view the view to be set to shown or not
diff --git a/SafetyCenter/Resources/res/values-af-v35/strings.xml b/SafetyCenter/Resources/res/values-af-v35/strings.xml
index 42ccf293c..ab7ce0129 100644
--- a/SafetyCenter/Resources/res/values-af-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-af-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Selnetwerksekuriteit"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Netwerktipe, enkripsie, kennisgewingkontroles"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-am-v35/strings.xml b/SafetyCenter/Resources/res/values-am-v35/strings.xml
index 948277aa8..96f9ade78 100644
--- a/SafetyCenter/Resources/res/values-am-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-am-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"የተንቀሳቃሽ ስልክ አውታረ መረብ ደህንነት"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"የአውታረ መረብ ዓይነት፣ ምስጠራ፣ የማሳወቂያ መቆጣጠሪያዎች"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ar-v35/strings.xml b/SafetyCenter/Resources/res/values-ar-v35/strings.xml
index 969edb241..4cf1c9a07 100644
--- a/SafetyCenter/Resources/res/values-ar-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ar-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"أمان شبكة الجوّال"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"عناصر التحكم في نوع الشبكة والتشفير والإشعارات"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-as-v35/strings.xml b/SafetyCenter/Resources/res/values-as-v35/strings.xml
index 5923f97cd..3d658276a 100644
--- a/SafetyCenter/Resources/res/values-as-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-as-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"চেলুলাৰ নেটৱৰ্কৰ সুৰক্ষা"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"নেটৱৰ্কৰ প্ৰকাৰ, এনক্ৰিপশ্বন, জাননীৰ নিয়ন্ত্ৰণসমূহ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-az-v35/strings.xml b/SafetyCenter/Resources/res/values-az-v35/strings.xml
index 39ea9a982..33b8aa0da 100644
--- a/SafetyCenter/Resources/res/values-az-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-az-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobil şəbəkə təhlükəsizliyi"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Şəbəkə növü, şifrələmə, bildiriş nizamlayıcıları"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml b/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml
index c877922b0..6584b80b5 100644
--- a/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-b+sr+Latn-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Bezbednost mobilne mreže"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tip mreže, šifrovanje, kontrole obaveštenja"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-be-v35/strings.xml b/SafetyCenter/Resources/res/values-be-v35/strings.xml
index 27799b191..61d96987a 100644
--- a/SafetyCenter/Resources/res/values-be-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-be-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Бяспека сотавай сеткі"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тып сеткі, шыфраванне, налады апавяшчэнняў"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-bg-v35/strings.xml b/SafetyCenter/Resources/res/values-bg-v35/strings.xml
index bb0de817f..09060c431 100644
--- a/SafetyCenter/Resources/res/values-bg-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-bg-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Сигурност на мобилната мрежа"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тип мрежа, шифроване, контроли за известията"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-bn-v35/strings.xml b/SafetyCenter/Resources/res/values-bn-v35/strings.xml
index 6b8104a04..27ec98325 100644
--- a/SafetyCenter/Resources/res/values-bn-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-bn-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"মোবাইল নেটওয়ার্কের সুরক্ষা"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"নেটওয়ার্কের ধরন, এনক্রিপশন, বিজ্ঞপ্তির নিয়ন্ত্রণ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-bs-v35/strings.xml b/SafetyCenter/Resources/res/values-bs-v35/strings.xml
index fc5a58c4d..e962785aa 100644
--- a/SafetyCenter/Resources/res/values-bs-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-bs-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sigurnost mobilne mreže"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Vrsta mreže, šifriranje i kontrole obavještenja"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ca-v35/strings.xml b/SafetyCenter/Resources/res/values-ca-v35/strings.xml
index 6a76c3032..7517723a5 100644
--- a/SafetyCenter/Resources/res/values-ca-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ca-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Seguretat de la xarxa mòbil"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipus de xarxa, encriptació, controls de notificació"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-cs-v35/strings.xml b/SafetyCenter/Resources/res/values-cs-v35/strings.xml
index c09ce3722..443d815e2 100644
--- a/SafetyCenter/Resources/res/values-cs-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-cs-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Zabezpečení mobilní sítě"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Nastavení typu sítě, šifrování a oznámení"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-da-v35/strings.xml b/SafetyCenter/Resources/res/values-da-v35/strings.xml
index e5c3c2173..25c638325 100644
--- a/SafetyCenter/Resources/res/values-da-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-da-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sikkerhed for mobilnetværk"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Netværkstype, kryptering, notifikationsstyring"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<string name="private_space_title" msgid="6158245041481535879">"Privat område"</string>
<string name="private_space_summary" msgid="529869826714610294">"Konfigurer et privat rum m.m."</string>
<string name="private_space_search_terms" msgid="4820808478299116258">"Privat område"</string>
diff --git a/SafetyCenter/Resources/res/values-de-v35/strings.xml b/SafetyCenter/Resources/res/values-de-v35/strings.xml
index 3cff5bf65..5c3818eaa 100644
--- a/SafetyCenter/Resources/res/values-de-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-de-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sicherheit von Mobilfunknetzen"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Netzwerktyp, Verschlüsselung, Benachrichtigungseinstellungen"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<string name="private_space_title" msgid="6158245041481535879">"Privates Profil"</string>
<string name="private_space_summary" msgid="529869826714610294">"Privaten Bereich einrichten und mehr"</string>
<string name="private_space_search_terms" msgid="4820808478299116258">"Privates Profil"</string>
diff --git a/SafetyCenter/Resources/res/values-el-v35/strings.xml b/SafetyCenter/Resources/res/values-el-v35/strings.xml
index 51e8f6580..3b1c02a6d 100644
--- a/SafetyCenter/Resources/res/values-el-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-el-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Ασφάλεια δικτύου κινητής τηλεφωνίας"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Τύπος δικτύου, κρυπτογράφηση, στοιχεία ελέγχου ειδοποιήσεων"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml
index 41d4bb4ef..42d1921e2 100644
--- a/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rAU-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobile network security"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Network type, encryption, notification controls"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml
index b5de7b0ef..c8dea5d1f 100644
--- a/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rCA-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Cellular network security"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Network type, encryption, notification controls"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml
index 41d4bb4ef..42d1921e2 100644
--- a/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rGB-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobile network security"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Network type, encryption, notification controls"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml
index 41d4bb4ef..42d1921e2 100644
--- a/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rIN-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobile network security"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Network type, encryption, notification controls"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml b/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml
index 4b9327829..998df375a 100644
--- a/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-en-rXC-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎Cellular network security‎‏‎‎‏‎"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎Network type, encryption, notification controls‎‏‎‎‏‎"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml b/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml
index b6227fa5f..7b63e6630 100644
--- a/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-es-rUS-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Seguridad de red móvil"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de red, encriptación, controles de notificaciones"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-es-v35/strings.xml b/SafetyCenter/Resources/res/values-es-v35/strings.xml
index fcd0a9870..775de899b 100644
--- a/SafetyCenter/Resources/res/values-es-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-es-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Seguridad de la red móvil"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de red, cifrado, controles de notificaciones"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-et-v35/strings.xml b/SafetyCenter/Resources/res/values-et-v35/strings.xml
index dab6f073e..0fdaadbe2 100644
--- a/SafetyCenter/Resources/res/values-et-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-et-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobiilsidevõrgu turvalisus"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Võrgu tüüp, krüpteerimine, märguannete juhtnupud"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-eu-v35/strings.xml b/SafetyCenter/Resources/res/values-eu-v35/strings.xml
index 02e53aedd..d61be7014 100644
--- a/SafetyCenter/Resources/res/values-eu-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-eu-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sare mugikorraren segurtasuna"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Sare mota, enkriptatzea, jakinarazpenak kontrolatzeko aukerak"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-fa-v35/strings.xml b/SafetyCenter/Resources/res/values-fa-v35/strings.xml
index 45b2b8605..ee5e56422 100644
--- a/SafetyCenter/Resources/res/values-fa-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-fa-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"امنیت شبکه تلفن همراه"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"نوع شبکه، رمزگذاری، کنترل‌های اعلان"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-fi-v35/strings.xml b/SafetyCenter/Resources/res/values-fi-v35/strings.xml
index e280f71e1..52594a08c 100644
--- a/SafetyCenter/Resources/res/values-fi-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-fi-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobiiliverkon tietoturva"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Verkon tyyppi, salaus, ilmoitusvalinnat"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml b/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml
index dbae68c8e..d762c9db0 100644
--- a/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-fr-rCA-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sécurité du réseau cellulaire"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Contrôles du type de réseau, du chiffrement et des notifications"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-fr-v35/strings.xml b/SafetyCenter/Resources/res/values-fr-v35/strings.xml
index 306c769ae..1371aa9f2 100644
--- a/SafetyCenter/Resources/res/values-fr-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-fr-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sécurité des réseaux mobiles"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Type de réseau, chiffrement, paramètres de notifications"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-gl-v35/strings.xml b/SafetyCenter/Resources/res/values-gl-v35/strings.xml
index c3ef9f8d8..4275d9484 100644
--- a/SafetyCenter/Resources/res/values-gl-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-gl-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Seguranza da rede de telefonía móbil"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de rede, encriptación, controis de notificacións"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-gu-v35/strings.xml b/SafetyCenter/Resources/res/values-gu-v35/strings.xml
index a3eb9ff61..a4a781e12 100644
--- a/SafetyCenter/Resources/res/values-gu-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-gu-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"સેલ્યુલર નેટવર્ક સંબંધી સુરક્ષા"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"નેટવર્કનો પ્રકાર, એન્ક્રિપ્શન, નોટિફિકેશનના નિયંત્રણો"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-hi-v35/strings.xml b/SafetyCenter/Resources/res/values-hi-v35/strings.xml
index 6a3d68007..c0a084f7b 100644
--- a/SafetyCenter/Resources/res/values-hi-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-hi-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"मोबाइल नेटवर्क की सुरक्षा"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"नेटवर्क टाइप, एन्क्रिप्ट करने का तरीका, सूचनाएं कंट्रोल करने की सेटिंग"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-hr-v35/strings.xml b/SafetyCenter/Resources/res/values-hr-v35/strings.xml
index 20a0c34ba..f9ce54f32 100644
--- a/SafetyCenter/Resources/res/values-hr-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-hr-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sigurnost mobilne mreže"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Vrsta mreže, šifriranje, kontrole obavijesti"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-hu-v35/strings.xml b/SafetyCenter/Resources/res/values-hu-v35/strings.xml
index 561aefc34..0c77b2181 100644
--- a/SafetyCenter/Resources/res/values-hu-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-hu-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobilhálózat biztonsága"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Hálózattípus, titkosítás, értesítésvezérlők"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-hy-v35/strings.xml b/SafetyCenter/Resources/res/values-hy-v35/strings.xml
index 9e6cde773..1b9c3ffdc 100644
--- a/SafetyCenter/Resources/res/values-hy-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-hy-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Բջջային ցանցի անվտանգություն"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Ցանցի տեսակը, գաղտնագրում, ծանուցումների կառավարում"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-in-v35/strings.xml b/SafetyCenter/Resources/res/values-in-v35/strings.xml
index 924d010c6..6e91010d7 100644
--- a/SafetyCenter/Resources/res/values-in-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-in-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Keamanan jaringan seluler"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Jenis jaringan, enkripsi, kontrol notifikasi"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-is-v35/strings.xml b/SafetyCenter/Resources/res/values-is-v35/strings.xml
index 3ee0b4078..94951412b 100644
--- a/SafetyCenter/Resources/res/values-is-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-is-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Öryggi farsímakerfis"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tegund netkerfis, dulkóðun, tilkynningastýringar"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-it-v35/strings.xml b/SafetyCenter/Resources/res/values-it-v35/strings.xml
index 6161a1f24..5f98b4d0b 100644
--- a/SafetyCenter/Resources/res/values-it-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-it-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sicurezza rete mobile"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo di rete, crittografia, controlli di notifica"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-iw-v35/strings.xml b/SafetyCenter/Resources/res/values-iw-v35/strings.xml
index adcea4384..577721d76 100644
--- a/SafetyCenter/Resources/res/values-iw-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-iw-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"אבטחת הרשת הסלולרית"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"סוג הרשת, הצפנה, אמצעי בקרה של התראות"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ja-v35/strings.xml b/SafetyCenter/Resources/res/values-ja-v35/strings.xml
index c7c9d3fe4..8b5244ea5 100644
--- a/SafetyCenter/Resources/res/values-ja-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ja-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"モバイル ネットワークのセキュリティ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ネットワークの種類、暗号化、通知の管理"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ka-v35/strings.xml b/SafetyCenter/Resources/res/values-ka-v35/strings.xml
index 4549e2578..479aa5f30 100644
--- a/SafetyCenter/Resources/res/values-ka-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ka-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ფიჭური ქსელის უსაფრთხოება"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ქსელის ტიპი, დაშიფვრა, შეტყობინებების მართვის საშუალებები"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-kk-v35/strings.xml b/SafetyCenter/Resources/res/values-kk-v35/strings.xml
index d7f9d50ca..cd667373c 100644
--- a/SafetyCenter/Resources/res/values-kk-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-kk-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Ұялы желі қауіпсіздігі"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Желі түрі, шифрлауды, хабарландыруды басқару элементтері"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-km-v35/strings.xml b/SafetyCenter/Resources/res/values-km-v35/strings.xml
index 2dac2a0d6..28324bd25 100644
--- a/SafetyCenter/Resources/res/values-km-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-km-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"សុវត្ថិភាពបណ្ដាញចល័ត"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ប្រភេទបណ្ដាញ ការអ៊ីនគ្រីប ការគ្រប់គ្រងការជូនដំណឹង"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-kn-v35/strings.xml b/SafetyCenter/Resources/res/values-kn-v35/strings.xml
index 821c577b6..d86c54b2a 100644
--- a/SafetyCenter/Resources/res/values-kn-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-kn-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ಸೆಲ್ಯುಲಾರ್ ನೆಟ್‌ವರ್ಕ್ ಭದ್ರತೆ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ, ಎನ್‌ಕ್ರಿಪ್ಶನ್, ನೋಟಿಫಿಕೇಶನ್ ಕಂಟ್ರೋಲ್‌ಗಳು"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ko-v35/strings.xml b/SafetyCenter/Resources/res/values-ko-v35/strings.xml
index 4cde1dd2c..19900d3ad 100644
--- a/SafetyCenter/Resources/res/values-ko-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ko-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"셀룰러 네트워크 보안"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"네트워크 유형, 암호화, 알림 설정"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ky-v35/strings.xml b/SafetyCenter/Resources/res/values-ky-v35/strings.xml
index a0dd4cd57..540d1b351 100644
--- a/SafetyCenter/Resources/res/values-ky-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ky-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Мобилдик тармактын коопсуздугу"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тармактын түрү, шифрлөө, билдирмелерди башкаруу элементтери"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-lo-v35/strings.xml b/SafetyCenter/Resources/res/values-lo-v35/strings.xml
index 731ab407c..6de5852c2 100644
--- a/SafetyCenter/Resources/res/values-lo-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-lo-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ຄວາມປອດໄພຂອງເຄືອຂ່າຍມືຖື"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ປະເພດເຄືອຂ່າຍ, ການເຂົ້າລະຫັດ, ການຄວບຄຸມການແຈ້ງເຕືອນ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-lt-v35/strings.xml b/SafetyCenter/Resources/res/values-lt-v35/strings.xml
index cccfd5465..6e28e6cea 100644
--- a/SafetyCenter/Resources/res/values-lt-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-lt-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobiliojo ryšio tinklo sauga"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tinklo tipas, šifruotė, pranešimų valdikliai"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-lv-v35/strings.xml b/SafetyCenter/Resources/res/values-lv-v35/strings.xml
index 3c5cf9224..e39d2ea02 100644
--- a/SafetyCenter/Resources/res/values-lv-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-lv-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobilā tīkla drošība"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tīkla veids, šifrējums, paziņojumu vadīklas"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-mk-v35/strings.xml b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
index 244d8c340..5ecb3db51 100644
--- a/SafetyCenter/Resources/res/values-mk-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Безбедност на мобилната мрежа"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Контроли за известувања на тип мрежа, шифрирање"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ml-v35/strings.xml b/SafetyCenter/Resources/res/values-ml-v35/strings.xml
index 4772cb9af..2923b81c7 100644
--- a/SafetyCenter/Resources/res/values-ml-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ml-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"സെല്ലുലാർ നെറ്റ്‌വർക്ക് സുരക്ഷ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"നെറ്റ്‌വർക്ക് തരം, എൻ‍ക്രിപ്ഷൻ, അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-mn-v35/strings.xml b/SafetyCenter/Resources/res/values-mn-v35/strings.xml
index afcb7f960..1ec4acfc4 100644
--- a/SafetyCenter/Resources/res/values-mn-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-mn-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Үүрэн холбооны сүлжээний аюулгүй байдал"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Сүлжээний төрөл, шифрлэлт, мэдэгдлийн тохиргоо"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-mr-v35/strings.xml b/SafetyCenter/Resources/res/values-mr-v35/strings.xml
index 39bbededf..768af9303 100644
--- a/SafetyCenter/Resources/res/values-mr-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-mr-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"मोबाइल नेटवर्कची सुरक्षा"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"नेटवर्क प्रकार, एन्क्रिप्शन, सूचना नियंत्रणे"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ms-v35/strings.xml b/SafetyCenter/Resources/res/values-ms-v35/strings.xml
index 6be1180bb..a15f04b43 100644
--- a/SafetyCenter/Resources/res/values-ms-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ms-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Keselamatan rangkaian selular"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Jenis rangkaian, penyulitan, kawalan pemberitahuan"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-my-v35/strings.xml b/SafetyCenter/Resources/res/values-my-v35/strings.xml
index 0e5fed737..dd6a9cdda 100644
--- a/SafetyCenter/Resources/res/values-my-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-my-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ဆယ်လူလာကွန်ရက် လုံခြုံရေး"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ကွန်ရက်အမျိုးအစား၊ အသွင်ဝှက်ခြင်း၊ အကြောင်းကြားချက် သတ်မှတ်ချက်များ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-nb-v35/strings.xml b/SafetyCenter/Resources/res/values-nb-v35/strings.xml
index 7f5142b96..ab403952c 100644
--- a/SafetyCenter/Resources/res/values-nb-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-nb-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Sikkerhet for mobilnettverk"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Nettverkstype, kryptering, varselskontroller"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ne-v35/strings.xml b/SafetyCenter/Resources/res/values-ne-v35/strings.xml
index 226388fbe..4c79b5b10 100644
--- a/SafetyCenter/Resources/res/values-ne-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ne-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"मोबाइल नेटवर्कको सुरक्षा"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"नेटवर्कको प्रकार, इन्क्रिप्सन, सूचनाका सेटिङ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-nl-v35/strings.xml b/SafetyCenter/Resources/res/values-nl-v35/strings.xml
index c0990f160..ac2beee11 100644
--- a/SafetyCenter/Resources/res/values-nl-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-nl-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Beveiliging van mobiele netwerken"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Netwerktype, versleuteling, beheeropties voor meldingen"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-or-v35/strings.xml b/SafetyCenter/Resources/res/values-or-v35/strings.xml
index ede3b5e80..5e546c5db 100644
--- a/SafetyCenter/Resources/res/values-or-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-or-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ସେଲୁଲାର ନେଟୱାର୍କ ସୁରକ୍ଷା"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ନେଟୱାର୍କ ପ୍ରକାର, ଏନକ୍ରିପସନ, ବିଜ୍ଞପ୍ତି ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-pa-v35/strings.xml b/SafetyCenter/Resources/res/values-pa-v35/strings.xml
index 8aeb6fb28..985f3b144 100644
--- a/SafetyCenter/Resources/res/values-pa-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-pa-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"ਸੈਲਿਊਲਰ ਨੈੱਟਵਰਕ ਸੁਰੱਖਿਆ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ, ਇਨਕ੍ਰਿਪਸ਼ਨ, ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-pl-v35/strings.xml b/SafetyCenter/Resources/res/values-pl-v35/strings.xml
index 3ce6984ac..0d6747501 100644
--- a/SafetyCenter/Resources/res/values-pl-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-pl-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Zabezpieczenia sieci komórkowej"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Typ sieci, szyfrowanie, ustawienia powiadomień"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml
index a9806e3db..10178f3a2 100644
--- a/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-rBR-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Segurança da rede celular"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de rede, criptografia, controles de notificação"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml
index fc0990db0..9456eb00c 100644
--- a/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-rPT-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Segurança da rede móvel"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de rede, encriptação, controlos de notificação"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-pt-v35/strings.xml b/SafetyCenter/Resources/res/values-pt-v35/strings.xml
index a9806e3db..10178f3a2 100644
--- a/SafetyCenter/Resources/res/values-pt-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-pt-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Segurança da rede celular"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipo de rede, criptografia, controles de notificação"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ro-v35/strings.xml b/SafetyCenter/Resources/res/values-ro-v35/strings.xml
index 1a6a5f43a..96a80f9d3 100644
--- a/SafetyCenter/Resources/res/values-ro-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ro-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Securitatea rețelei de date mobile"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tipul de rețea, criptarea, comenzile pentru notificări"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ru-v35/strings.xml b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
index 3c1862167..89e6939a5 100644
--- a/SafetyCenter/Resources/res/values-ru-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Безопасность мобильной сети"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тип сети, шифрование, управление уведомлениями"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-si-v35/strings.xml b/SafetyCenter/Resources/res/values-si-v35/strings.xml
index 1cf86f0e3..8e8b48460 100644
--- a/SafetyCenter/Resources/res/values-si-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-si-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"සෙලියුලර් ජාල ආරක්ෂාව"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ජාල වර්ගය, සංකේතනය, දැනුම්දීම් පාලන"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sk-v35/strings.xml b/SafetyCenter/Resources/res/values-sk-v35/strings.xml
index a0e64827e..fbd935881 100644
--- a/SafetyCenter/Resources/res/values-sk-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sk-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Zabezpečenie mobilnej siete"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Ovládanie typu siete, šifrovania a upozornení"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sl-v35/strings.xml b/SafetyCenter/Resources/res/values-sl-v35/strings.xml
index b36740d1e..317b8eb36 100644
--- a/SafetyCenter/Resources/res/values-sl-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sl-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Varnost mobilnega omrežja"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Vrsta omrežja, šifriranje, kontrolniki obvestil"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sq-v35/strings.xml b/SafetyCenter/Resources/res/values-sq-v35/strings.xml
index 6d0a4b25e..067302507 100644
--- a/SafetyCenter/Resources/res/values-sq-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sq-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Siguria e rrjetit celular"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Lloji i rrjetit, enkriptimi, kontrollet e njoftimeve"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sr-v35/strings.xml b/SafetyCenter/Resources/res/values-sr-v35/strings.xml
index 814988c5c..66ee14e01 100644
--- a/SafetyCenter/Resources/res/values-sr-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sr-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Безбедност мобилне мреже"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тип мреже, шифровање, контроле обавештења"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sv-v35/strings.xml b/SafetyCenter/Resources/res/values-sv-v35/strings.xml
index 108d28f75..1fa3ff62a 100644
--- a/SafetyCenter/Resources/res/values-sv-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sv-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Säkerhet för mobilnätverk"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Nätverkstyp, kryptering, aviseringsinställningar"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-sw-v35/strings.xml b/SafetyCenter/Resources/res/values-sw-v35/strings.xml
index 44a51760d..3ddbf11cd 100644
--- a/SafetyCenter/Resources/res/values-sw-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-sw-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Usalama wa mtandao wa simu"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Aina ya mtandao, usimbaji fiche, vidhibiti vya arifa"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ta-v35/strings.xml b/SafetyCenter/Resources/res/values-ta-v35/strings.xml
index ba518fb66..ca7ac1f84 100644
--- a/SafetyCenter/Resources/res/values-ta-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ta-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"மொபைல் நெட்வொர்க் பாதுகாப்பு"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"நெட்வொர்க் வகை, என்க்ரிப்ஷன், அறிவிப்புக் கட்டுப்பாடுகள்"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-te-v35/strings.xml b/SafetyCenter/Resources/res/values-te-v35/strings.xml
index 757be94a0..08691b56a 100644
--- a/SafetyCenter/Resources/res/values-te-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-te-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"సెల్యులర్ నెట్‌వర్క్ సెక్యూరిటీ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"నెట్‌వర్క్ రకం, ఎన్‌క్రిప్షన్, నోటిఫికేషన్ కంట్రోల్స్"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-th-v35/strings.xml b/SafetyCenter/Resources/res/values-th-v35/strings.xml
index 8c00c1270..dd9796b66 100644
--- a/SafetyCenter/Resources/res/values-th-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-th-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"การรักษาความปลอดภัยของเครือข่ายมือถือ"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"ประเภทเครือข่าย การเข้ารหัส ส่วนควบคุมการแจ้งเตือน"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-tl-v35/strings.xml b/SafetyCenter/Resources/res/values-tl-v35/strings.xml
index 990f0e505..855fbee18 100644
--- a/SafetyCenter/Resources/res/values-tl-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-tl-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Seguridad ng cellular network"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Network type, pag-encrypt, mga kontrol sa notification"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-tr-v35/strings.xml b/SafetyCenter/Resources/res/values-tr-v35/strings.xml
index 1c84e5cae..670836e65 100644
--- a/SafetyCenter/Resources/res/values-tr-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-tr-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Hücresel ağ güvenliği"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Ağ türü, şifreleme, bildirim kontrolleri"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-uk-v35/strings.xml b/SafetyCenter/Resources/res/values-uk-v35/strings.xml
index f8b981114..70ac6516a 100644
--- a/SafetyCenter/Resources/res/values-uk-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-uk-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Безпека мобільної мережі"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тип мережі, шифрування, налаштування сповіщень"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-ur-v35/strings.xml b/SafetyCenter/Resources/res/values-ur-v35/strings.xml
index 5dd2ca23b..d9b81b1ce 100644
--- a/SafetyCenter/Resources/res/values-ur-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ur-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"سیلولر نیٹ ورک سیکیورٹی"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"نیٹ ورک کی قسم، مرموز کاری، نوٹیفکیشن کنٹرولز"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-uz-v35/strings.xml b/SafetyCenter/Resources/res/values-uz-v35/strings.xml
index f7822cfd5..bd6adac69 100644
--- a/SafetyCenter/Resources/res/values-uz-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-uz-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Mobil tarmoq xavfsizligi"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Tarmoq turi, shifrlash, bildirishnomalar boshqaruvi"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-vi-v35/strings.xml b/SafetyCenter/Resources/res/values-vi-v35/strings.xml
index cefc57faa..e067e7585 100644
--- a/SafetyCenter/Resources/res/values-vi-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-vi-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Chế độ bảo mật mạng di động"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Loại mạng, quy trình mã hoá, quyền kiểm soát thông báo"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml
index e0be57584..a613a9e13 100644
--- a/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rCN-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"移动网络安全性"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"网络类型、加密、通知控件"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml
index 334da7a63..f46f3b083 100644
--- a/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rHK-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"流動網絡安全性"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"網絡類型、加密、通知控制項"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml b/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml
index 2e21b3047..d9b6a4ff6 100644
--- a/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-zh-rTW-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"行動網路安全性"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"網路類型、加密、通知控制選項"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/SafetyCenter/Resources/res/values-zu-v35/strings.xml b/SafetyCenter/Resources/res/values-zu-v35/strings.xml
index 4576f3dd0..237b2974f 100644
--- a/SafetyCenter/Resources/res/values-zu-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-zu-v35/strings.xml
@@ -19,6 +19,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="cellular_network_security_title" msgid="2986431282931510973">"Ukuphepha kwenethiwekhi yeselula"</string>
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Uhlobo lwenethiwekhi, ukubethela, izilawuli zezaziso"</string>
+ <string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<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>
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index 3bec682a1..3077dd290 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -2,7 +2,8 @@ package: "com.android.permission.flags"
container: "com.android.permission"
flag {
- name: "device_aware_permission_grant"
+ name: "device_aware_permission_grant_enabled"
+ is_fixed_read_only: true
namespace: "permissions"
description: "Enables device aware grant permission flow"
bug: "292252664"
diff --git a/framework-s/api/module-lib-current.txt b/framework-s/api/module-lib-current.txt
index 14f71782e..97a8623b3 100644
--- a/framework-s/api/module-lib-current.txt
+++ b/framework-s/api/module-lib-current.txt
@@ -15,6 +15,7 @@ package android.app.role {
public final class RoleManager {
method @Nullable public String getBrowserRoleHolder(int);
+ method @FlaggedApi("android.permission.flags.get_emergency_role_holder_api_enabled") @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getEmergencyRoleHolder(int);
method @Nullable public String getSmsRoleHolder(int);
method @Nullable @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public boolean setBrowserRoleHolder(@Nullable String, int);
}
diff --git a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
index e304fc21e..74062165e 100644
--- a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
+++ b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java
@@ -33,7 +33,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.RemoteException;
import android.permission.flags.Flags;
-import android.provider.Settings;
import android.util.ArraySet;
import androidx.annotation.NonNull;
@@ -330,20 +329,23 @@ public final class EnhancedConfirmationManager {
}
/**
- * Gets an intent that will open the "Restricted setting" dialog for the specified app.
+ * Gets an intent that will open the "Restricted setting" dialog for the specified package
+ * and setting.
*
* <p>The "Restricted setting" dialog is a dialog that informs the user that the operation
* they've attempted to perform is restricted, and provides them with a link explaining how to
* proceed.
*
- * @param packageName package name of the application to open the dialog for
+ * @param packageName package name of the restricted application
+ * @param settingIdentifier identifier of the restricted setting
* @throws NameNotFoundException if the provided package was not found
*/
public @NonNull Intent createRestrictedSettingDialogIntent(@NonNull String packageName,
@NonNull String settingIdentifier) throws NameNotFoundException {
- Intent intent = new Intent(Settings.ACTION_SHOW_RESTRICTED_SETTING_DIALOG);
+ Intent intent = new Intent(ACTION_SHOW_ECM_RESTRICTED_SETTING_DIALOG);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(Intent.EXTRA_UID, getPackageUid(packageName));
+ intent.putExtra(Intent.EXTRA_SUBJECT, settingIdentifier);
return intent;
}
diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl
index 0aef871e6..522967630 100644
--- a/framework-s/java/android/app/role/IRoleManager.aidl
+++ b/framework-s/java/android/app/role/IRoleManager.aidl
@@ -74,6 +74,8 @@ interface IRoleManager {
String getSmsRoleHolder(int userId);
+ String getEmergencyRoleHolder(int userId);
+
boolean isRoleVisibleAsUser(in String roleName, int userId);
boolean isApplicationVisibleForRoleAsUser(in String roleName, in String packageName,
diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java
index fe27d50f3..4b8c9b388 100644
--- a/framework-s/java/android/app/role/RoleManager.java
+++ b/framework-s/java/android/app/role/RoleManager.java
@@ -975,6 +975,28 @@ public final class RoleManager {
}
/**
+ * Allows getting the role holder for {@link #ROLE_EMERGENCY} without requiring
+ * {@link Manifest.permission#OBSERVE_ROLE_HOLDERS}.
+ *
+ * @param userId the user ID to get the default emergency package for
+ * @return the package name of the default emergency app, or {@code null} if none
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED)
+ @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Nullable
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public String getEmergencyRoleHolder(@UserIdInt int userId) {
+ try {
+ return mService.getEmergencyRoleHolder(userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Check whether a role should be visible to user.
*
* @param roleName name of the role to check for
diff --git a/service/Android.bp b/service/Android.bp
index 97a1a89ee..f9342deb9 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -163,6 +163,7 @@ java_library {
":statslog-service-permission-java-gen",
],
libs: [
+ "androidx.annotation_annotation",
"framework-statsd.stubs.module_lib",
],
apex_available: [
diff --git a/service/java/com/android/ecm/EnhancedConfirmationService.java b/service/java/com/android/ecm/EnhancedConfirmationService.java
index 7e45d4c05..4b866157a 100644
--- a/service/java/com/android/ecm/EnhancedConfirmationService.java
+++ b/service/java/com/android/ecm/EnhancedConfirmationService.java
@@ -16,6 +16,7 @@
package com.android.ecm;
+import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.UserIdInt;
@@ -91,7 +92,7 @@ public class EnhancedConfirmationService extends SystemService {
ArrayMap<String, List<byte[]>> trustedPackageMap = new ArrayMap<>();
for (SignedPackage signedPackage : signedPackages) {
ArrayList<byte[]> certDigests = (ArrayList<byte[]>) trustedPackageMap.computeIfAbsent(
- signedPackage.getPkgName(), pkgName -> new ArrayList<>(1));
+ signedPackage.getPackageName(), packageName -> new ArrayList<>(1));
certDigests.add(signedPackage.getCertificateDigest());
}
return trustedPackageMap;
@@ -114,7 +115,26 @@ public class EnhancedConfirmationService extends SystemService {
private static final ArraySet<String> PROTECTED_SETTINGS = new ArraySet<>();
static {
+ // Runtime permissions
+ // TODO(b/310654818): Construct this list by permission group instead of by permission
+ PROTECTED_SETTINGS.add(Manifest.permission.READ_PHONE_STATE);
+ PROTECTED_SETTINGS.add(Manifest.permission.READ_PHONE_NUMBERS);
+ PROTECTED_SETTINGS.add(Manifest.permission.CALL_PHONE);
+ PROTECTED_SETTINGS.add(Manifest.permission.ADD_VOICEMAIL);
+ PROTECTED_SETTINGS.add(Manifest.permission.USE_SIP);
+ PROTECTED_SETTINGS.add(Manifest.permission.ANSWER_PHONE_CALLS);
+ PROTECTED_SETTINGS.add(Manifest.permission.ACCEPT_HANDOVER);
+
+ PROTECTED_SETTINGS.add(Manifest.permission.SEND_SMS);
+ PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_SMS);
+ PROTECTED_SETTINGS.add(Manifest.permission.READ_SMS);
+ PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_MMS);
+ PROTECTED_SETTINGS.add(Manifest.permission.RECEIVE_WAP_PUSH);
+ PROTECTED_SETTINGS.add(Manifest.permission.READ_CELL_BROADCASTS);
+ // TODO(b/310654818): Add other explicitly protected runtime permissions
+ // App ops
PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
+ PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS);
// Default application roles.
PROTECTED_SETTINGS.add(RoleManager.ROLE_ASSISTANT);
PROTECTED_SETTINGS.add(RoleManager.ROLE_BROWSER);
@@ -124,6 +144,8 @@ public class EnhancedConfirmationService extends SystemService {
PROTECTED_SETTINGS.add(RoleManager.ROLE_HOME);
PROTECTED_SETTINGS.add(RoleManager.ROLE_SMS);
PROTECTED_SETTINGS.add(RoleManager.ROLE_WALLET);
+ // Other settings
+ PROTECTED_SETTINGS.add(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE);
// TODO(b/310654015): Add other explicitly protected settings
}
@@ -217,7 +239,7 @@ public class EnhancedConfirmationService extends SystemService {
private void enforcePermissions(@NonNull String methodName, @UserIdInt int userId) {
UserUtils.enforceCrossUserPermission(userId, false, methodName, mContext);
- mContext.enforceCallingPermission(
+ mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MANAGE_ENHANCED_CONFIRMATION_STATES, methodName);
}
@@ -323,10 +345,15 @@ public class EnhancedConfirmationService extends SystemService {
}
private boolean isSettingEcmProtected(@NonNull String settingIdentifier) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ return false;
+ }
+
if (PROTECTED_SETTINGS.contains(settingIdentifier)) {
return true;
}
- // TODO(b/310654818): If this is a permission, coerce it into a PermissionGroup.
// TODO(b/310218979): Add role selections as protected settings
return false;
}
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index a2a6bab35..f441ce2f3 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -930,6 +930,33 @@ public class RoleService extends SystemService implements RoleUserState.Callback
}
@Override
+ public String getEmergencyRoleHolder(int userId) {
+ final Context context = getContext();
+ UserUtils.enforceCrossUserPermission(userId, false, "getEmergencyRoleHolder", context);
+ if (!UserUtils.isUserExistent(userId, getContext())) {
+ Log.e(LOG_TAG, "user " + userId + " does not exist");
+ return null;
+ }
+
+ getContext().enforceCallingOrSelfPermission(
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "getEmergencyRoleHolder");
+
+ final String packageName;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser(
+ RoleManager.ROLE_EMERGENCY, userId));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName,
+ userId, context)) {
+ return null;
+ }
+ return packageName;
+ }
+
+ @Override
public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) {
UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser",
getContext());
diff --git a/service/java/com/android/safetycenter/UserProfileGroup.java b/service/java/com/android/safetycenter/UserProfileGroup.java
index 2f4ab17e4..46a440bf7 100644
--- a/service/java/com/android/safetycenter/UserProfileGroup.java
+++ b/service/java/com/android/safetycenter/UserProfileGroup.java
@@ -324,7 +324,7 @@ public final class UserProfileGroup {
case PROFILE_TYPE_PRIVATE:
//TODO(b/286539356) add the new feature flag protection when available.
return mPrivateProfileRunning
- ? new int[] {} : new int[] {mPrivateProfileUserId};
+ ? new int[] {mPrivateProfileUserId} : new int[] {};
default:
Log.w(TAG, "Unexpected profile type " + profileType);
return new int[] {};
diff --git a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt
index 2efc6718e..d70375459 100644
--- a/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt
+++ b/tests/cts/permission/src/android/permission/cts/DevicePermissionsTest.kt
@@ -21,6 +21,7 @@ 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.PERSISTENT_DEVICE_ID_DEFAULT
import android.companion.virtual.VirtualDeviceManager.VirtualDevice
import android.companion.virtual.VirtualDeviceParams
import android.content.Context
@@ -63,6 +64,7 @@ class DevicePermissionsTest {
private lateinit var virtualDevice: VirtualDevice
private lateinit var virtualDeviceContext: Context
+ private lateinit var persistentDeviceId: String
private lateinit var permissionManager: PermissionManager
@@ -75,7 +77,8 @@ class DevicePermissionsTest {
Manifest.permission.CREATE_VIRTUAL_DEVICE,
Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
- Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.GET_RUNTIME_PERMISSIONS
)
@Rule @JvmField val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@@ -92,6 +95,7 @@ class DevicePermissionsTest {
)
virtualDeviceContext = defaultDeviceContext.createDeviceContext(virtualDevice.deviceId)
permissionManager = virtualDeviceContext.getSystemService(PermissionManager::class.java)!!
+ persistentDeviceId = virtualDevice.persistentDeviceId!!
runShellCommandOrThrow("pm install -r $TEST_APK")
}
@@ -120,13 +124,9 @@ class DevicePermissionsTest {
@Test
fun testNonDeviceAwareRuntimePermissionGrantIsInherited() {
- grantPermissionAndAssertGranted(Manifest.permission.READ_CONTACTS, defaultDeviceContext)
+ grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext)
- assertPermission(
- Manifest.permission.READ_CONTACTS,
- PERMISSION_GRANTED,
- virtualDeviceContext
- )
+ assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_GRANTED, virtualDeviceContext)
}
@RequiresFlagsEnabled(
@@ -135,22 +135,18 @@ class DevicePermissionsTest {
)
@Test
fun testDeviceAwareRuntimePermissionIsRevoked() {
- grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext)
- revokePermissionAndAssertDenied(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ revokePermissionAndAssertDenied(DEVICE_AWARE_PERMISSION, virtualDeviceContext)
}
@Test
fun testNonDeviceAwareRuntimePermissionIsRevokedForDefaultDevice() {
- grantPermissionAndAssertGranted(Manifest.permission.READ_CONTACTS, defaultDeviceContext)
- assertPermission(
- Manifest.permission.READ_CONTACTS,
- PERMISSION_GRANTED,
- virtualDeviceContext
- )
+ grantPermissionAndAssertGranted(NON_DEVICE_AWARE_PERMISSION, defaultDeviceContext)
+ assertPermission(NON_DEVICE_AWARE_PERMISSION, 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)
+ revokePermissionAndAssertDenied(NON_DEVICE_AWARE_PERMISSION, virtualDeviceContext)
+ assertPermission(NON_DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, defaultDeviceContext)
}
@Test
@@ -165,9 +161,9 @@ class DevicePermissionsTest {
@Test
fun testOneTimePermissionIsRevoked() {
- grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext)
virtualDeviceContext.packageManager.updatePermissionFlags(
- Manifest.permission.RECORD_AUDIO,
+ DEVICE_AWARE_PERMISSION,
TEST_PACKAGE_NAME,
FLAG_PERMISSION_ONE_TIME,
FLAG_PERMISSION_ONE_TIME,
@@ -182,11 +178,7 @@ class DevicePermissionsTest {
IMPORTANCE_FOREGROUND_SERVICE
)
eventually {
- assertPermission(
- Manifest.permission.RECORD_AUDIO,
- PERMISSION_DENIED,
- virtualDeviceContext
- )
+ assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext)
}
}
@@ -196,15 +188,11 @@ class DevicePermissionsTest {
)
@Test
fun testRevokeSelfPermissionOnKill() {
- grantPermissionAndAssertGranted(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ grantPermissionAndAssertGranted(DEVICE_AWARE_PERMISSION, virtualDeviceContext)
- revokeSelfPermission(Manifest.permission.RECORD_AUDIO, virtualDeviceContext)
+ revokeSelfPermission(DEVICE_AWARE_PERMISSION, virtualDeviceContext)
eventually {
- assertPermission(
- Manifest.permission.RECORD_AUDIO,
- PERMISSION_DENIED,
- virtualDeviceContext
- )
+ assertPermission(DEVICE_AWARE_PERMISSION, PERMISSION_DENIED, virtualDeviceContext)
}
}
@@ -214,30 +202,28 @@ class DevicePermissionsTest {
)
@Test
fun testGrantAndRevokeDeviceAwarePermissionByPersistentDeviceId() {
- val deviceAwarePermission = Manifest.permission.RECORD_AUDIO
+ val deviceAwarePermission = DEVICE_AWARE_PERMISSION
permissionManager.grantRuntimePermission(
TEST_PACKAGE_NAME,
deviceAwarePermission,
- virtualDevice.persistentDeviceId!!
+ persistentDeviceId
)
assertThat(
- PermissionManager.checkPermission(
+ permissionManager.checkPermission(
deviceAwarePermission,
TEST_PACKAGE_NAME,
- virtualDevice.persistentDeviceId!!,
- virtualDeviceContext.userId
+ virtualDevice.persistentDeviceId!!
)
)
.isEqualTo(PERMISSION_GRANTED)
assertThat(
- PermissionManager.checkPermission(
+ permissionManager.checkPermission(
deviceAwarePermission,
TEST_PACKAGE_NAME,
- VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT,
- defaultDeviceContext.userId
+ VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT
)
)
.isEqualTo(PERMISSION_DENIED)
@@ -245,16 +231,15 @@ class DevicePermissionsTest {
permissionManager.revokeRuntimePermission(
TEST_PACKAGE_NAME,
deviceAwarePermission,
- virtualDevice.persistentDeviceId!!,
+ persistentDeviceId,
"test"
)
assertThat(
- PermissionManager.checkPermission(
+ permissionManager.checkPermission(
deviceAwarePermission,
TEST_PACKAGE_NAME,
- virtualDevice.persistentDeviceId!!,
- virtualDeviceContext.userId
+ virtualDevice.persistentDeviceId!!
)
)
.isEqualTo(PERMISSION_DENIED)
@@ -266,7 +251,7 @@ class DevicePermissionsTest {
)
@Test
fun testUpdateAndGetPermissionFlagsByPersistentDeviceId() {
- val deviceAwarePermission = Manifest.permission.RECORD_AUDIO
+ val deviceAwarePermission = DEVICE_AWARE_PERMISSION
val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
val flag = FLAG_PERMISSION_USER_SET
@@ -274,7 +259,7 @@ class DevicePermissionsTest {
permissionManager.getPermissionFlags(
TEST_PACKAGE_NAME,
deviceAwarePermission,
- virtualDevice.persistentDeviceId!!
+ persistentDeviceId
)
)
.isEqualTo(0)
@@ -282,7 +267,7 @@ class DevicePermissionsTest {
permissionManager.updatePermissionFlags(
TEST_PACKAGE_NAME,
deviceAwarePermission,
- virtualDevice.persistentDeviceId!!,
+ persistentDeviceId,
flagMask,
flag
)
@@ -291,12 +276,213 @@ class DevicePermissionsTest {
permissionManager.getPermissionFlags(
TEST_PACKAGE_NAME,
deviceAwarePermission,
- virtualDevice.persistentDeviceId!!
+ persistentDeviceId
)
)
.isEqualTo(FLAG_PERMISSION_USER_SET)
}
+ @RequiresFlagsEnabled(
+ Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED
+ )
+ @Test
+ fun testAllPermissionStatesApiGrantForVirtualDevice() {
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)
+ .isEmpty()
+ )
+ .isTrue()
+
+ permissionManager.grantRuntimePermission(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ persistentDeviceId
+ )
+
+ val permissionStateMap =
+ permissionManager.getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)
+ assertThat(permissionStateMap.size).isEqualTo(1)
+ assertThat(permissionStateMap[DEVICE_AWARE_PERMISSION]!!.isGranted).isTrue()
+ assertThat(permissionStateMap[DEVICE_AWARE_PERMISSION]!!.flags).isEqualTo(0)
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)
+ .contains(DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+
+ permissionManager.revokeRuntimePermission(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ persistentDeviceId,
+ "test"
+ )
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)
+ .contains(DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+ }
+
+ @RequiresFlagsEnabled(
+ Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED
+ )
+ @Test
+ fun testAllPermissionStatesApiFlagsForVirtualDevice() {
+ val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
+ val flag = FLAG_PERMISSION_USER_SET
+
+ assertThat(permissionManager.getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId))
+ .isEmpty()
+
+ permissionManager.updatePermissionFlags(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ persistentDeviceId,
+ flagMask,
+ flag
+ )
+
+ assertThat(
+ hasPermission(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[
+ DEVICE_AWARE_PERMISSION]!!
+ .flags,
+ flag
+ )
+ )
+ .isTrue()
+
+ assertThat(
+ hasPermission(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)[
+ DEVICE_AWARE_PERMISSION]!!
+ .flags,
+ FLAG_PERMISSION_USER_FIXED
+ )
+ )
+ .isFalse()
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @Test
+ fun testAllPermissionStatesApiGrantForDefaultDevice() {
+ permissionManager.grantRuntimePermission(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ PERSISTENT_DEVICE_ID_DEFAULT
+ )
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[
+ DEVICE_AWARE_PERMISSION]!!
+ .isGranted
+ )
+ .isTrue()
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)
+ .contains(DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+
+ permissionManager.revokeRuntimePermission(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ PERSISTENT_DEVICE_ID_DEFAULT,
+ "test"
+ )
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)
+ .contains(DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @Test
+ fun testAllPermissionStatesApiFlagsForDefaultDevice() {
+ val flagMask = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
+ val flag = FLAG_PERMISSION_USER_SET
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)
+ .contains(DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+
+ permissionManager.updatePermissionFlags(
+ TEST_PACKAGE_NAME,
+ DEVICE_AWARE_PERMISSION,
+ PERSISTENT_DEVICE_ID_DEFAULT,
+ flagMask,
+ flag
+ )
+
+ assertThat(
+ hasPermission(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[
+ DEVICE_AWARE_PERMISSION]!!
+ .flags,
+ flag
+ )
+ )
+ .isTrue()
+
+ assertThat(
+ hasPermission(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[
+ DEVICE_AWARE_PERMISSION]!!
+ .flags,
+ FLAG_PERMISSION_USER_FIXED
+ )
+ )
+ .isFalse()
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @Test
+ fun testAllPermissionStatesApiThatNonDeviceAwareRuntimePermissionGrantIsNotInherited() {
+ permissionManager.grantRuntimePermission(
+ TEST_PACKAGE_NAME,
+ NON_DEVICE_AWARE_PERMISSION,
+ PERSISTENT_DEVICE_ID_DEFAULT
+ )
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, PERSISTENT_DEVICE_ID_DEFAULT)[
+ NON_DEVICE_AWARE_PERMISSION]!!
+ .isGranted
+ )
+ .isTrue()
+
+ assertThat(
+ permissionManager
+ .getAllPermissionStates(TEST_PACKAGE_NAME, persistentDeviceId)
+ .contains(NON_DEVICE_AWARE_PERMISSION)
+ )
+ .isFalse()
+ }
+
+ private fun hasPermission(permissionFlags: Int, permissionBit: Int): Boolean =
+ permissionFlags and permissionBit != 0
+
private fun revokeSelfPermission(permissionName: String, context: Context) {
val intent = Intent(PERMISSION_SELF_REVOKE_INTENT)
intent.setClassName(TEST_PACKAGE_NAME, PERMISSION_SELF_REVOKE_RECEIVER)
@@ -345,5 +531,8 @@ class DevicePermissionsTest {
"android.permission.cts.appthatrequestpermission.REVOKE_SELF_PERMISSION"
private const val PERMISSION_SELF_REVOKE_RECEIVER =
"android.permission.cts.appthatrequestpermission.RevokeSelfPermissionReceiver"
+
+ private const val DEVICE_AWARE_PERMISSION = Manifest.permission.RECORD_AUDIO
+ private const val NON_DEVICE_AWARE_PERMISSION = Manifest.permission.READ_CONTACTS
}
}
diff --git a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java
index 543a3cbbd..33975f91c 100644
--- a/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java
+++ b/tests/cts/permission/src/android/permission/cts/PermissionUpdateListenerTest.java
@@ -122,7 +122,8 @@ public class PermissionUpdateListenerTest {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED})
public void testVirtualDeviceGrantPermissionNotifyListener() throws InterruptedException {
VirtualDeviceManager.VirtualDevice virtualDevice =
mVirtualDeviceManager.createVirtualDevice(
@@ -165,7 +166,8 @@ public class PermissionUpdateListenerTest {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED})
public void testVirtualDeviceRevokePermissionNotifyListener() throws InterruptedException {
VirtualDeviceManager.VirtualDevice virtualDevice =
mVirtualDeviceManager.createVirtualDevice(
@@ -204,7 +206,8 @@ public class PermissionUpdateListenerTest {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED)
+ @RequiresFlagsEnabled({Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED})
public void testVirtualDeviceUpdatePermissionFlagsNotifyListener() throws InterruptedException {
VirtualDeviceManager.VirtualDevice virtualDevice =
mVirtualDeviceManager.createVirtualDevice(
diff --git a/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt b/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
index 17327c6d4..57a2f7fcb 100644
--- a/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
+++ b/tests/cts/permission/src/android/permission/cts/RevokeSawPermissionTest.kt
@@ -17,6 +17,7 @@
package android.permission.cts
import android.content.pm.PackageManager
+import android.platform.test.annotations.AppModeFull
import android.platform.test.annotations.AsbSecurityTest
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After
@@ -27,6 +28,7 @@ private val APP_PKG_NAME = "android.permission.cts.usesystemalertwindowpermissio
private val APK_22 = "/data/local/tmp/cts-permission/" + "CtsAppThatRequestsSystemAlertWindow22.apk"
private val APK_23 = "/data/local/tmp/cts-permission/" + "CtsAppThatRequestsSystemAlertWindow23.apk"
+@AppModeFull
class RevokeSawPermissionTest {
fun installApp(apk: String) {
diff --git a/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java b/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
index 8609e3379..0c1c885be 100644
--- a/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
+++ b/tests/cts/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
@@ -17,7 +17,6 @@
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;
@@ -49,12 +48,6 @@ public class ServicesInstantAppsCannotAccessTests {
}
@Test
- public void cannotGetFingerprintManager() {
- assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
- FINGERPRINT_SERVICE));
- }
-
- @Test
public void cannotGetShortcutManager() {
assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
SHORTCUT_SERVICE));
diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
index 359b4e5fd..c199c7660 100644
--- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
+++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/DeviceAwarePermissionGrantTest.kt
@@ -76,6 +76,10 @@ class DeviceAwarePermissionGrantTest {
uninstallPackage(APP_PACKAGE_NAME, requireSuccess = false)
}
+ @RequiresFlagsEnabled(
+ Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED,
+ Flags.FLAG_DEVICE_AWARE_PERMISSIONS_ENABLED
+ )
@Test
fun onHostDevice_requestPermissionForHostDevice_shouldGrantPermission() {
testGrantPermissionForDevice(
@@ -171,16 +175,6 @@ class DeviceAwarePermissionGrantTest {
mFakeVirtualDeviceRule.virtualDevice.deviceId,
expectPermissionGrantedOnRemoteDevice
)
-
- assertAppHasPermissionForDeviceUsingAllPermissionStatesApi(
- defaultDeviceContext,
- expectPermissionGrantedOnRemoteDevice
- )
-
- assertAppHasPermissionForDefaultDeviceUsingAllPermissionStatesApi(
- defaultDeviceContext,
- expectPermissionGrantedOnDefaultDevice
- )
}
private fun requestPermissionOnDevice(displayId: Int, targetDeviceId: Int) {
@@ -220,48 +214,6 @@ class DeviceAwarePermissionGrantTest {
}
}
- private fun assertAppHasPermissionForDeviceUsingAllPermissionStatesApi(
- context: Context,
- expectPermissionGranted: Boolean
- ) {
- val vdm = context.getSystemService(VirtualDeviceManager::class.java)!!
- val persistentDeviceIds = vdm.allPersistentDeviceIds
-
- if (persistentDeviceIds.isEmpty()) {
- Assert.assertEquals(expectPermissionGranted, false)
- } else {
- Assert.assertEquals(1, persistentDeviceIds.size)
- val permMap =
- PermissionUtils.getAllPermissionStates(
- context,
- APP_PACKAGE_NAME,
- persistentDeviceIds.toList()[0]
- )
- val grantedList =
- permMap.filter { it.key == Manifest.permission.CAMERA }.map { it.value.isGranted }
- if (grantedList.isNotEmpty()) {
- Assert.assertEquals(1, grantedList.size)
- Assert.assertEquals(expectPermissionGranted, grantedList[0])
- } else {
- Assert.assertFalse(expectPermissionGranted)
- }
- }
- }
-
- private fun assertAppHasPermissionForDefaultDeviceUsingAllPermissionStatesApi(
- context: Context,
- expectPermissionGranted: Boolean
- ) {
- val permMap =
- PermissionUtils.getAllPermissionStates(
- context,
- APP_PACKAGE_NAME,
- PERSISTENT_DEVICE_ID_DEFAULT
- )
- Assert.assertNotNull(permMap[Manifest.permission.CAMERA])
- Assert.assertEquals(expectPermissionGranted, permMap[Manifest.permission.CAMERA]?.isGranted)
- }
-
companion object {
const val APK_DIRECTORY = "/data/local/tmp/cts-permissionmultidevice"
const val APP_APK_PATH_STREAMING = "${APK_DIRECTORY}/CtsAccessRemoteDeviceCamera.apk"
diff --git a/tests/cts/permissionpolicy/Android.bp b/tests/cts/permissionpolicy/Android.bp
index 7a481b7ff..a2860e264 100644
--- a/tests/cts/permissionpolicy/Android.bp
+++ b/tests/cts/permissionpolicy/Android.bp
@@ -25,8 +25,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts-permission",
- "mcts-permission",
],
libs: ["android.test.base"],
static_libs: [
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
index 5244887ee..ef85fdf60 100644
--- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -1657,6 +1657,15 @@
android:description="@string/permdesc_cameraHeadlessSystemUser"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows camera access of allowlisted driver assistance apps
+ to be controlled separately.
+ <p> Not for use by third-party applications.
+ @FlaggedApi("com.android.internal.camera.flags.camera_privacy_allowlist")
+ @hide
+ -->
+ <permission android:name="android.permission.CAMERA_PRIVACY_ALLOWLIST"
+ android:protectionLevel="signature|privileged" />
+
<!-- ====================================================================== -->
<!-- Permissions for accessing the device sensors -->
<!-- ====================================================================== -->
@@ -3564,6 +3573,14 @@
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING"
android:protectionLevel="internal|role" />
+ <!-- Allows an application to use audit logging API.
+ @hide
+ @SystemApi
+ @FlaggedApi("android.app.admin.flags.security_log_v2_enabled")
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_AUDIT_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.
@@ -3667,6 +3684,14 @@
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_LOCK"
android:protectionLevel="internal|role" />
+ <!-- Allows an application to manage policy related to theft detection.
+ @FlaggedApi("android.app.admin.flags.device_theft_api_enabled")
+ @hide
+ @SystemApi
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_THEFT_DETECTION"
+ 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.
@@ -3704,6 +3729,25 @@
-->
<permission android:name="android.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS"
android:protectionLevel="internal|role" />
+ <!-- Allows an application to manage policy related to block package uninstallation.
+ @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+ -->
+
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to camera toggle.
+ @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_CAMERA_TOGGLE"
+ android:protectionLevel="internal|role" />
+
+ <!-- Allows an application to manage policy related to microphone toggle.
+ @FlaggedApi("android.app.admin.flags.dedicated_device_control_api_enabled")
+ -->
+ <permission android:name="android.permission.MANAGE_DEVICE_POLICY_MICROPHONE_TOGGLE"
+ 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_*
@@ -4984,6 +5028,33 @@
<permission android:name="android.permission.BIND_VPN_SERVICE"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an app to use the on-device intelligence service.
+ <p>Protection level: signature|privileged
+ @hide
+ @FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence")
+ -->
+ <permission android:name="android.permission.USE_ON_DEVICE_INTELLIGENCE"
+ android:protectionLevel="signature|privileged" />
+
+
+ <!-- @SystemApi Allows an app to bind the on-device intelligence service.
+ <p>Protection level: signature|privileged
+ @hide
+ @FlaggedApi("android.app.ondeviceintelligence.flags.enable_ondevice_intelligence")
+ -->
+ <permission android:name="android.permission.BIND_ON_DEVICE_INTELLIGENCE_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
+
+ <!-- @SystemApi Allows an app to bind the on-device trusted service.
+ <p>Protection level: signature|privileged
+ @hide
+ @FlaggedApi("android.app.ondeviceintelligence.flags.enable_ondevice_intelligence")
+ -->
+ <permission android:name="android.permission.BIND_ON_DEVICE_TRUSTED_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
@@ -6962,10 +7033,10 @@
<permission android:name="android.permission.MANAGE_SPEECH_RECOGNITION"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows an application to manage the content suggestions service.
+ <!-- @SystemApi Allows an application to interact with 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" />
+ android:protectionLevel="signature|role" />
<!-- @SystemApi Allows an application to manage the app predictions service.
@hide <p>Not for use by third-party applications.</p> -->
@@ -7233,7 +7304,7 @@
Allows an accessibility service to observe motion events without consuming them. -->
<permission android:name="android.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING"
android:protectionLevel="signature" />
-
+
<!-- @SystemApi Allows an app to grant a profile owner access to device identifiers.
<p>Not for use by third-party applications.
@deprecated
@@ -7719,7 +7790,7 @@
@SystemApi
@hide -->
<permission android:name="android.permission.GET_APP_METADATA"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- @hide @SystemApi Allows an application to stage HealthConnect's remote data so that
HealthConnect can later integrate it. -->
@@ -7818,14 +7889,6 @@
<permission android:name="android.permission.MANAGE_DISPLAYS"
android:protectionLevel="signature" />
- <!-- @SystemApi Allows apps to reset hotword training data egress count for testing.
- <p>CTS tests will use UiAutomation.AdoptShellPermissionIdentity() to gain access.
- <p>Protection level: signature
- @FlaggedApi("android.service.voice.flags.allow_training_data_egress_from_hds")
- @hide -->
- <permission android:name="android.permission.RESET_HOTWORD_TRAINING_DATA_EGRESS_COUNT"
- android:protectionLevel="signature" />
-
<!-- @SystemApi Allows an app to track all preparations for a complete factory reset.
<p>Protection level: signature|privileged
@FlaggedApi("android.permission.flags.factory_reset_prep_permission_apis")
diff --git a/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml b/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml
index d87fe65b8..4729d44c2 100644
--- a/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/automotive_android_manifest.xml
@@ -218,10 +218,10 @@
android:protectionLevel="signature|privileged"
android:label="@string/car_permission_label_read_impact_sensors"
android:description="@string/car_permission_desc_read_impact_sensors"/>
- <permission android:name="android.car.permission.READ_HEAD_UP_DISPLAY"
+ <permission android:name="android.car.permission.READ_HEAD_UP_DISPLAY_STATUS"
android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_read_head_up_display"
- android:description="@string/car_permission_desc_read_head_up_display"/>
+ android:label="@string/car_permission_label_read_head_up_display_status"
+ android:description="@string/car_permission_desc_read_head_up_display_status"/>
<permission android:name="android.car.permission.CONTROL_HEAD_UP_DISPLAY"
android:protectionLevel="signature|privileged"
android:label="@string/car_permission_label_control_head_up_display"
diff --git a/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml b/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml
index 49e45fc01..0b92f5ef1 100644
--- a/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml
+++ b/tests/cts/permissionui/UsePermissionAppLatest/AndroidManifest.xml
@@ -20,6 +20,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="android.permissionui.cts.usepermission">
+ <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+ <uses-permission android:name="android.permission.CALL_PHONE"/>
+
<!-- Request two different permissions within the same group -->
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt
index 6f80ea5d6..8c300e328 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BasePermissionTest.kt
@@ -281,9 +281,13 @@ abstract class BasePermissionTest {
protected fun installPackageViaSession(
apkName: String,
appMetadata: PersistableBundle? = null,
- packageSource: Int? = null
+ packageSource: Int? = null,
+ allowlistedRestrictedPermissions: Set<String>? = null
) {
- val (sessionId, session) = createPackageInstallerSession(packageSource)
+ val (sessionId, session) = createPackageInstallerSession(
+ packageSource,
+ allowlistedRestrictedPermissions
+ )
runWithShellPermissionIdentity {
writePackageInstallerSession(session, apkName)
if (appMetadata != null) {
@@ -448,10 +452,15 @@ abstract class BasePermissionTest {
}
private fun createPackageInstallerSession(
- packageSource: Int? = null
+ packageSource: Int? = null,
+ allowlistedRestrictedPermissions: Set<String>? = null
): Pair<Int, PackageInstaller.Session> {
// Create session
val sessionParam = SessionParams(SessionParams.MODE_FULL_INSTALL)
+ allowlistedRestrictedPermissions?.let {
+ sessionParam.setWhitelistedRestrictedPermissions(it)
+ }
+
if (packageSource != null) {
sessionParam.setPackageSource(packageSource)
}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
index d24f4fd27..42555c2d7 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -29,6 +29,7 @@ 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.SessionParams
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
@@ -63,6 +64,7 @@ import org.junit.Before
abstract class BaseUsePermissionTest : BasePermissionTest() {
companion object {
const val APP_APK_NAME_31 = "CtsUsePermissionApp31.apk"
+ const val APP_APK_NAME_LATEST = "CtsUsePermissionAppLatest.apk"
const val APP_APK_PATH_22 = "$APK_DIRECTORY/CtsUsePermissionApp22.apk"
const val APP_APK_PATH_22_CALENDAR_ONLY =
@@ -443,6 +445,17 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
)
}
+ protected fun installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ apkName: String
+ ) {
+ installPackageViaSession(
+ apkName,
+ AppMetadata.createDefaultAppMetadata(),
+ PACKAGE_SOURCE_DOWNLOADED_FILE,
+ allowlistedRestrictedPermissions = SessionParams.RESTRICTED_PERMISSIONS_ALL
+ )
+ }
+
protected fun installPackageWithInstallSourceAndMetadataFromOther(apkName: String) {
installPackageViaSession(
apkName,
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
index 4d1118a6f..4a505d1fd 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
@@ -16,6 +16,7 @@
package android.permissionui.cts
+import android.Manifest
import android.app.AppOpsManager
import android.app.Instrumentation
import android.app.ecm.EnhancedConfirmationManager
@@ -29,11 +30,14 @@ import android.platform.test.flag.junit.CheckFlagsRule
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
+import org.junit.Assume
+import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -41,8 +45,6 @@ import org.junit.Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName = "VanillaIceCream")
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
-
- private val apkName = APP_APK_NAME_31
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val context: Context = instrumentation.targetContext
private val ecm by lazy { context.getSystemService(EnhancedConfirmationManager::class.java)!! }
@@ -51,10 +53,19 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@JvmField
val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+ @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))
+ }
+
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenStoreAppThenIsNotRestrictedFromProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromStore(apkName)
+ installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertFalse(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
}
@@ -63,7 +74,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenLocalAppThenIsRestrictedFromProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromLocalFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromLocalFile(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertTrue(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
}
@@ -72,7 +83,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenDownloadedThenAppIsRestrictedFromProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromDownloadedFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertTrue(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
}
@@ -81,7 +92,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenExplicitlyRestrictedAppThenIsRestrictedFromProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromStore(apkName)
+ installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertFalse(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
setAppEcmState(context, APP_PACKAGE_NAME, MODE_ERRORED)
@@ -92,7 +103,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenRestrictedAppThenIsNotRestrictedFromNonProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromDownloadedFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertFalse(ecm.isRestricted(APP_PACKAGE_NAME, NON_PROTECTED_SETTING)) }
}
@@ -101,7 +112,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenRestrictedAppThenClearRestrictionNotAllowedByDefault() {
- installPackageWithInstallSourceAndMetadataFromDownloadedFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertFalse(ecm.isClearRestrictionAllowed(APP_PACKAGE_NAME)) }
}
@@ -110,7 +121,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun givenRestrictedAppWhenClearRestrictionThenNotRestrictedFromProtectedSetting() {
- installPackageWithInstallSourceAndMetadataFromDownloadedFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
runWithShellPermissionIdentity {
eventually { assertTrue(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
ecm.setClearRestrictionAllowed(APP_PACKAGE_NAME)
@@ -123,14 +134,113 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun createRestrictedSettingDialogIntentReturnsIntent() {
- installPackageWithInstallSourceAndMetadataFromDownloadedFile(apkName)
+ installPackageWithInstallSourceAndMetadataFromDownloadedFile(APP_APK_NAME_LATEST)
val intent = ecm.createRestrictedSettingDialogIntent(APP_PACKAGE_NAME, PROTECTED_SETTING)
assertNotNull(intent)
}
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @Test
+ fun grantDialogBlocksRestrictedPermissionsOfSameGroupTogether() {
+ installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ APP_APK_NAME_LATEST
+ )
+
+ requestAppPermissionsAndAssertResult(
+ GROUP_1_PERMISSION_1_RESTRICTED to false,
+ GROUP_1_PERMISSION_2_RESTRICTED to false
+ ) {
+ click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS)
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @Test
+ fun grantDialogBlocksRestrictedPermissionsOfDifferentGroupsIndividually() {
+ installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ APP_APK_NAME_LATEST
+ )
+
+ requestAppPermissionsAndAssertResult(
+ GROUP_1_PERMISSION_1_RESTRICTED to false,
+ GROUP_2_PERMISSION_1_RESTRICTED to false,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @Test
+ fun grantDialogBlocksRestrictedGroupsThenRequestsUnrestrictedGroupsDespiteOutOfOrderRequest() {
+ installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ APP_APK_NAME_LATEST
+ )
+
+ requestAppPermissionsAndAssertResult(
+ GROUP_3_PERMISSION_1_UNRESTRICTED to true,
+ GROUP_2_PERMISSION_1_RESTRICTED to false,
+ GROUP_3_PERMISSION_2_UNRESTRICTED to true,
+ GROUP_2_PERMISSION_2_RESTRICTED to false,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @Test
+ fun grantDialogBlocksRestrictedGroupsThenRequestsUnrestrictedHighPriorityGroups() {
+ installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ APP_APK_NAME_LATEST
+ )
+
+ requestAppPermissionsAndAssertResult(
+ GROUP_3_PERMISSION_1_UNRESTRICTED to true,
+ GROUP_2_PERMISSION_1_RESTRICTED to false,
+ GROUP_1_PERMISSION_1_RESTRICTED to false,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @Test
+ fun grantDialogBlocksRestrictedGroupsThenRequestsUnrestrictedLowPriorityGroups() {
+ installPackageWithInstallSourceFromDownloadedFileAndAllowHardRestrictedPerms(
+ APP_APK_NAME_LATEST
+ )
+
+ requestAppPermissionsAndAssertResult(
+ GROUP_4_PERMISSION_1_UNRESTRICTED to true,
+ GROUP_2_PERMISSION_1_RESTRICTED to false,
+ GROUP_1_PERMISSION_1_RESTRICTED to false,
+ waitForWindowTransition = false
+ ) {
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ }
+ }
+
companion object {
+ private const val GROUP_1_PERMISSION_1_RESTRICTED = Manifest.permission.CALL_PHONE
+ private const val GROUP_1_PERMISSION_2_RESTRICTED = Manifest.permission.READ_PHONE_STATE
+ private const val GROUP_2_PERMISSION_1_RESTRICTED = Manifest.permission.SEND_SMS
+ private const val GROUP_2_PERMISSION_2_RESTRICTED = Manifest.permission.READ_SMS
+ private const val GROUP_3_PERMISSION_1_UNRESTRICTED =
+ Manifest.permission.ACCESS_FINE_LOCATION
+ private const val GROUP_3_PERMISSION_2_UNRESTRICTED =
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ private const val GROUP_4_PERMISSION_1_UNRESTRICTED = Manifest.permission.BODY_SENSORS
+
private const val NON_PROTECTED_SETTING = "example_setting_which_is_not_protected"
private const val PROTECTED_SETTING = "android:bind_accessibility_service"
private const val MODE_ERRORED = 2
diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp
index cf6b7ee8c..2a312976b 100644
--- a/tests/cts/role/Android.bp
+++ b/tests/cts/role/Android.bp
@@ -32,8 +32,8 @@ android_test {
"androidx.test.rules",
"compatibility-device-util-axt",
"ctstestrunner-axt",
- "truth",
"platform-test-annotations",
+ "truth",
],
test_suites: [
diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
index c53718ba4..fe9b8d578 100644
--- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
+++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
@@ -49,6 +49,7 @@ import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import android.provider.Telephony;
+import android.telephony.TelephonyManager;
import android.util.Pair;
import androidx.annotation.NonNull;
@@ -232,6 +233,25 @@ public class RoleManagerTest {
assertIsRoleHolder(ROLE_NAME, APP_PACKAGE_NAME, true);
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void requestRoleAndSelectRestrictedAppThenRestrictedSettingDialog() throws Exception {
+ assumeFalse(sIsWatch || sIsAutomotive || sIsTelevision);
+ runWithShellPermissionIdentity(
+ () -> setEnhancedConfirmationRestrictedAppOpMode(sContext, APP_PACKAGE_NAME,
+ AppOpsManager.MODE_ERRORED));
+
+ requestRole(ROLE_NAME);
+ waitFindObject(By.text(APP_LABEL).enabled(false))
+ .clickAndWait(Until.newWindow(), TIMEOUT_MILLIS);
+ waitFindObject(By.textContains("Restricted setting"), TIMEOUT_MILLIS);
+ pressBack();
+ respondToRoleRequest(false);
+ }
+
@Test
@FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
public void requestRoleFirstTimeNoDontAskAgain() throws Exception {
@@ -635,6 +655,8 @@ public class RoleManagerTest {
pressBack();
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
+ "VanillaIceCream")
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
@@ -652,11 +674,11 @@ public class RoleManagerTest {
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK)));
- waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).enabled(false).checked(
- false)).hasDescendant(By.text(APP_LABEL))).clickAndWait(Until.newWindow(),
+ waitFindObject(By.text(APP_LABEL).enabled(false)).clickAndWait(Until.newWindow(),
TIMEOUT_MILLIS);
- waitFindObject(By.textContains("Restricted setting"), UNEXPECTED_TIMEOUT_MILLIS);
+ waitFindObject(By.textContains("Restricted setting"), TIMEOUT_MILLIS);
+ pressBack();
pressBack();
}
@@ -1103,6 +1125,28 @@ public class RoleManagerTest {
assertThat(Telephony.Sms.getDefaultSmsPackage(sContext)).isEqualTo(APP_PACKAGE_NAME);
}
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream")
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_GET_EMERGENCY_ROLE_HOLDER_API_ENABLED)
+ public void telephonyManagerGetEmergencyAssistancePackageNameBackedByRole() throws Exception {
+ TelephonyManager telephonyManager = sContext.getSystemService(TelephonyManager.class);
+ List<String> emergencyRoleHolders = getRoleHolders(RoleManager.ROLE_EMERGENCY);
+
+ if (telephonyManager.isVoiceCapable()
+ && callWithShellPermissionIdentity(() ->
+ telephonyManager.isEmergencyAssistanceEnabled())) {
+ String emergencyAssistancePackageName = callWithShellPermissionIdentity(() ->
+ telephonyManager.getEmergencyAssistancePackage());
+ assertThat(emergencyRoleHolders).hasSize(1);
+ assertThat(emergencyAssistancePackageName).isEqualTo(emergencyRoleHolders.get(0));
+ } else {
+ assertThrows(IllegalStateException.class, () ->
+ callWithShellPermissionIdentity(() ->
+ telephonyManager.getEmergencyAssistancePackage()));
+ }
+ }
+
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S, codeName = "S")
@Test
public void cannotBypassRoleQualificationWithoutPermission() throws Exception {