summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/res/values-af/strings.xml8
-rw-r--r--PermissionController/res/values-b+sr+Latn/strings.xml6
-rw-r--r--PermissionController/res/values-cs/strings.xml2
-rw-r--r--PermissionController/res/values-da/strings.xml32
-rw-r--r--PermissionController/res/values-fi/strings.xml4
-rw-r--r--PermissionController/res/values-fr-rCA/strings.xml4
-rw-r--r--PermissionController/res/values-hi/strings.xml2
-rw-r--r--PermissionController/res/values-hr/strings.xml4
-rw-r--r--PermissionController/res/values-hy/strings.xml2
-rw-r--r--PermissionController/res/values-in/strings.xml2
-rw-r--r--PermissionController/res/values-my/strings.xml2
-rw-r--r--PermissionController/res/values-ne/strings.xml6
-rw-r--r--PermissionController/res/values-sr/strings.xml6
-rw-r--r--PermissionController/res/values-te/strings.xml2
-rw-r--r--PermissionController/res/values-v34/styles.xml1
-rw-r--r--PermissionController/res/values-zh-rTW/strings.xml4
-rw-r--r--PermissionController/res/values/strings.xml58
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java3
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java100
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/LocationProviderInterceptDialog.java37
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt2
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt5
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt45
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt63
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java7
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt76
-rw-r--r--SafetyCenter/Resources/res/values-in-v35/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-my-v35/strings.xml4
-rw-r--r--SafetyCenter/Resources/res/values-ru-v35/strings.xml4
-rw-r--r--tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt38
-rw-r--r--tests/cts/permissionui/Android.bp1
-rw-r--r--tests/cts/permissionui/AndroidTest.xml1
-rw-r--r--tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/Android.bp33
-rw-r--r--tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/AndroidManifest.xml39
-rw-r--r--tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity1.kt39
-rw-r--r--tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity2.kt (renamed from PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt)24
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt2
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt47
-rw-r--r--tests/cts/role/Android.bp2
-rw-r--r--tests/cts/role/AndroidTest.xml1
-rw-r--r--tests/cts/role/CtsRoleTestAppForProfile/Android.bp23
-rw-r--r--tests/cts/role/CtsRoleTestAppForProfile/AndroidManifest.xml36
-rw-r--r--tests/cts/role/src/android/app/role/cts/RoleManagerTest.java105
47 files changed, 691 insertions, 241 deletions
diff --git a/PermissionController/res/values-af/strings.xml b/PermissionController/res/values-af/strings.xml
index 7527ed691..370b296bc 100644
--- a/PermissionController/res/values-af/strings.xml
+++ b/PermissionController/res/values-af/strings.xml
@@ -194,12 +194,12 @@
<string name="precise_image_description" msgid="6349638632303619872">"Presiese ligging"</string>
<string name="approximate_image_description" msgid="938803699637069884">"Benaderde ligging"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Gebruik presiese ligging"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Wanneer presiese ligging af is, kan programme jou benaderde ligging bepaal"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Wanneer presiese ligging af is, kan apps jou benaderde ligging bepaal"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>-toestemming"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Toegang tot <xliff:g id="PERM">%1$s</xliff:g> vir hierdie program"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Toegang tot <xliff:g id="PERM">%1$s</xliff:g> vir hierdie app"</string>
<string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g>toegang vir hierdie app op <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Sien al <xliff:g id="APP">%1$s</xliff:g> se toestemmings"</string>
- <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Sien alle programme met hierdie toestemming"</string>
+ <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Sien alle apps met hierdie toestemming"</string>
<string name="assistant_mic_label" msgid="1011432357152323896">"Wys Assistent-mikrofoongebruik"</string>
<string name="unused_apps_category_title" msgid="2988455616845243901">"Instellings vir ongebruikte apps"</string>
<string name="auto_revoke_label" msgid="5068393642936571656">"Verwyder toestemmings as program nie gebruik word nie"</string>
@@ -654,7 +654,7 @@
<string name="data_sharing_updates_summary" msgid="764113985772233889">"Gaan apps na wat die manier waarop hulle jou liggingdata kan deel, verander het"</string>
<string name="data_sharing_updates_subtitle" msgid="6311537708950632329">"Hierdie apps het die manier waarop hulle jou liggingdata kan deel, verander. Hulle het dit dalk nie voorheen gedeel nie, of kan dit nou vir reklame- of bemarkingdoeleindes deel."</string>
<string name="data_sharing_updates_footer_message" msgid="1582711655172892107">"Die ontwikkelaars van hierdie apps het inligting oor hul datadelingpraktyke met ’n appwinkel gedeel. Hulle kan dit mettertyd opdateer.\n\nDatadelingpraktyke kan verskil op grond van jou appweergawe en -gebruik, streek en ouderdom."</string>
- <string name="learn_about_data_sharing" msgid="4200480587079488045">"Kom meer te wete oor datadeling"</string>
+ <string name="learn_about_data_sharing" msgid="4200480587079488045">"Meer inligting oor datadeling"</string>
<string name="shares_location_with_third_parties" msgid="2278051743742057767">"Jou liggingdata word nou met derde partye gedeel"</string>
<string name="shares_location_with_third_parties_for_advertising" msgid="1918588064014480513">"Jou liggingdata word nou met derde partye gedeel vir reklame of bemarking"</string>
<string name="updated_in_last_days" msgid="8371811947153042322">"{count,plural, =0{In die afgelope dag opgedateer}=1{In die afgelope dag opgedateer}other{In die afgelope # dae opgedateer}}"</string>
diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml
index fecf6f7c8..b13744b81 100644
--- a/PermissionController/res/values-b+sr+Latn/strings.xml
+++ b/PermissionController/res/values-b+sr+Latn/strings.xml
@@ -405,10 +405,10 @@
<string name="role_notes_short_label" msgid="8796604147546125285">"Aplikacija za beleške"</string>
<string name="role_notes_description" msgid="8496852798616883551">"Aplikacije koje vam omogućavaju da pravite beleške na uređaju"</string>
<string name="role_notes_search_keywords" msgid="7710756695666744631">"beleške"</string>
- <string name="role_wallet_label" msgid="3719419175656204207">"Podrazumevana aplikacija Novčanik"</string>
+ <string name="role_wallet_label" msgid="3719419175656204207">"Podrazumevana aplikacija novčanika"</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 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_description" msgid="3726535836165949838">"Aplikacije novčanika 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čanika?"</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>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Ne pitaj ponovo"</string>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 483dfd27a..f9afb6cb6 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -205,7 +205,7 @@
<string name="auto_revoke_label" msgid="5068393642936571656">"Odebrat oprávnění, pokud se aplikace nepoužívá"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Odebrat oprávnění a uvolnit místo"</string>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"Pozastavit aktivitu při nepoužívání"</string>
- <string name="unused_apps_label_v3" msgid="693340578642156657">"Spravovat aplikaci, pokud se nepoužívá"</string>
+ <string name="unused_apps_label_v3" msgid="693340578642156657">"Správa nepoužívané aplikace"</string>
<string name="unused_apps_summary" msgid="8839466950318403115">"Odebrat oprávnění, smazat dočasné soubory a zastavit oznámení"</string>
<string name="unused_apps_summary_v2" msgid="5011313200815115802">"Odebrat oprávnění, smazat dočasné soubory, zastavit oznámení a archivovat aplikaci"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"Pokud tuto aplikaci několik měsíců nepoužijete, kvůli ochraně vašich dat jí budou oprávnění odebrána."</string>
diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml
index 814c0242e..1f89fce34 100644
--- a/PermissionController/res/values-da/strings.xml
+++ b/PermissionController/res/values-da/strings.xml
@@ -181,8 +181,8 @@
<string name="permission_history_category_today" msgid="7496389369158806620">"I dag"</string>
<string name="permission_history_category_yesterday" msgid="7242517121222012521">"I går"</string>
<string name="app_permission_usage_title" msgid="6676802437831981822">"Brug af apptilladelser"</string>
- <string name="app_permission_usage_summary" msgid="390383661936709672">"Adgang: <xliff:g id="NUM">%1$s</xliff:g> gange. Samlet varighed: <xliff:g id="DURATION">%2$s</xliff:g>. Senest brugt for <xliff:g id="TIME">%3$s</xliff:g> siden."</string>
- <string name="app_permission_usage_summary_no_duration" msgid="3698475875179457400">"Adgang: <xliff:g id="NUM">%1$s</xliff:g> gange. Senest brugt for <xliff:g id="TIME">%2$s</xliff:g> siden."</string>
+ <string name="app_permission_usage_summary" msgid="390383661936709672">"Adgang: <xliff:g id="NUM">%1$s</xliff:g> gange. Samlet varighed: <xliff:g id="DURATION">%2$s</xliff:g>. Senest anvendt for <xliff:g id="TIME">%3$s</xliff:g> siden."</string>
+ <string name="app_permission_usage_summary_no_duration" msgid="3698475875179457400">"Adgang: <xliff:g id="NUM">%1$s</xliff:g> gange. Senest anvendt for <xliff:g id="TIME">%2$s</xliff:g> siden."</string>
<string name="app_permission_button_allow" msgid="5808039516494774647">"Tillad"</string>
<string name="app_permission_button_allow_all_files" msgid="1792232272599018825">"Tillad administration af alle filer"</string>
<string name="app_permission_button_allow_media_only" msgid="2834282724426046154">"Tillad kun adgang til mediefiler"</string>
@@ -224,9 +224,9 @@
<string name="unused_apps_page_title" msgid="6986983535677572559">"Apps, du ikke bruger"</string>
<string name="unused_apps_page_summary" msgid="1867593913217272155">"Hvis en app ikke bruges i et par måneder, sker følgende:\n\n• Tilladelser fjernes for at beskytte dine data\n• Notifikationer stoppes for at spare på batteriet\n• Midlertidige filer fjernes for at frigøre plads\n\nHvis du vil aktivere tilladelser og notifikationer igen, skal du åbne appen."</string>
<string name="unused_apps_page_tv_summary" msgid="2624911608663778308">"Hvis en app ikke bruges i en måned, sker følgende:\n\n• Tilladelser fjernes for at beskytte dine data\n• Midlertidige filer fjernes for at frigøre plads\n\nHvis du vil aktivere tilladelserne igen, skal du åbne appen."</string>
- <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Sidst åbnet for mere end # måned siden}one{Sidst åbnet for mere end # måned siden}other{Sidst åbnet for mere end # måneder siden}}"</string>
+ <string name="last_opened_category_title" msgid="8796557894614236128">"{count,plural, =1{Senest åbnet for mere end # måned siden}one{Senest åbnet for mere end # måned siden}other{Senest åbnet for mere end # måneder siden}}"</string>
<string name="last_opened_summary" msgid="5248984030024968808">"Appen blev sidst åbnet <xliff:g id="DATE">%s</xliff:g>"</string>
- <string name="last_opened_summary_short" msgid="1646067226191176825">"Sidst åbnet <xliff:g id="DATE">%s</xliff:g>"</string>
+ <string name="last_opened_summary_short" msgid="1646067226191176825">"Senest åbnet <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="app_permission_footer_special_file_access" msgid="1884202176147657788">"Hvis du tillader administration af alle filer, får denne app adgang og tilladelse til at ændre og slette alle filer på enhedens almindelige lagerplads og tilsluttede lagerenheder. Appen kan få adgang til filer uden at spørge dig først."</string>
<string name="special_file_access_dialog" msgid="583804114020740610">"Vil du give denne app adgang og tilladelse til at ændre og slette filer på denne enhed og tilsluttede lagerenheder? Appen kan få adgang til filer uden at spørge dig først."</string>
<string name="permission_description_summary_generic" msgid="5401399408814903391">"Apps med denne tilladelse kan <xliff:g id="DESCRIPTION">%1$s</xliff:g>"</string>
@@ -319,24 +319,24 @@
<string name="permission_subtitle_media_only" msgid="8917869683764720717">"Mediefiler"</string>
<string name="permission_subtitle_all_files" msgid="4982613338298067862">"Alle filer"</string>
<string name="permission_subtitle_background" msgid="8916750995309083180">"Altid tilladt"</string>
- <string name="app_perms_24h_access" msgid="99069906850627181">"Sidst brugt <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
- <string name="app_perms_24h_access_yest" msgid="5411926024794555022">"Sidst brugt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
- <string name="app_perms_7d_access" msgid="4945055548894683751">"Sidst brugt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g>"</string>
+ <string name="app_perms_24h_access" msgid="99069906850627181">"Senest anvendt <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
+ <string name="app_perms_24h_access_yest" msgid="5411926024794555022">"Senest anvendt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g>"</string>
+ <string name="app_perms_7d_access" msgid="4945055548894683751">"Senest anvendt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g>"</string>
<string name="app_perms_content_provider_24h" msgid="1055526027667508972">"Brugt inden for de seneste 24 timer"</string>
<string name="app_perms_content_provider_7d" msgid="3215454898257814868">"Brugt inden for de seneste 7 dage"</string>
- <string name="app_perms_24h_access_background" msgid="3413674718969576843">"Sidst brugt <xliff:g id="TIME_DATE">%1$s</xliff:g> • Altid tilladt"</string>
- <string name="app_perms_24h_access_yest_background" msgid="9174750810998076725">"Sidst brugt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Altid tilladt"</string>
- <string name="app_perms_7d_access_background" msgid="408099213372185627">"Sidst brugt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Altid tilladt"</string>
+ <string name="app_perms_24h_access_background" msgid="3413674718969576843">"Senest anvendt <xliff:g id="TIME_DATE">%1$s</xliff:g> • Altid tilladt"</string>
+ <string name="app_perms_24h_access_yest_background" msgid="9174750810998076725">"Senest anvendt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Altid tilladt"</string>
+ <string name="app_perms_7d_access_background" msgid="408099213372185627">"Senest anvendt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Altid tilladt"</string>
<string name="app_perms_content_provider_24h_background" msgid="3825902995186961496">"Brugt inden for de seneste 24 timer • Altid tilladt"</string>
<string name="app_perms_content_provider_7d_background" msgid="4818839672116463542">"Brugt inden for de seneste 7 dage • Altid tilladt"</string>
- <string name="app_perms_24h_access_media_only" msgid="6651699644199132054">"Sidst brugt <xliff:g id="TIME_DATE">%1$s</xliff:g> • Medier"</string>
- <string name="app_perms_24h_access_yest_media_only" msgid="7213187706424998792">"Sidst brugt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Medier"</string>
- <string name="app_perms_7d_access_media_only" msgid="1031096653668235200">"Sidst brugt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Mediefiler"</string>
+ <string name="app_perms_24h_access_media_only" msgid="6651699644199132054">"Senest anvendt <xliff:g id="TIME_DATE">%1$s</xliff:g> • Medier"</string>
+ <string name="app_perms_24h_access_yest_media_only" msgid="7213187706424998792">"Senest anvendt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Medier"</string>
+ <string name="app_perms_7d_access_media_only" msgid="1031096653668235200">"Senest anvendt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Mediefiler"</string>
<string name="app_perms_content_provider_24h_media_only" msgid="7797963000596179491">"Brugt inden for de seneste 24 timer • Mediefiler"</string>
<string name="app_perms_content_provider_7d_media_only" msgid="8446239884570262243">"Brugt inden for de seneste 7 dage • Mediefiler"</string>
- <string name="app_perms_24h_access_all_files" msgid="8902360456978159091">"Sidst brugt <xliff:g id="TIME_DATE">%1$s</xliff:g> • Alle filer"</string>
- <string name="app_perms_24h_access_yest_all_files" msgid="5708424073126844909">"Sidst brugt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Alle filer"</string>
- <string name="app_perms_7d_access_all_files" msgid="8246193786397635824">"Sidst brugt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Alle filer"</string>
+ <string name="app_perms_24h_access_all_files" msgid="8902360456978159091">"Senest åbnet <xliff:g id="TIME_DATE">%1$s</xliff:g> • Alle filer"</string>
+ <string name="app_perms_24h_access_yest_all_files" msgid="5708424073126844909">"Senest anvendt i går kl. <xliff:g id="TIME_DATE">%1$s</xliff:g> • Alle filer"</string>
+ <string name="app_perms_7d_access_all_files" msgid="8246193786397635824">"Senest anvendt <xliff:g id="TIME_DATE_0">%1$s</xliff:g> kl. <xliff:g id="TIME_DATE_1">%2$s</xliff:g> • Alle filer"</string>
<string name="app_perms_content_provider_24h_all_files" msgid="573104317727770850">"Brugt inden for de seneste 24 timer • Alle filer"</string>
<string name="app_perms_content_provider_7d_all_files" msgid="7962416229708835558">"Brugt inden for de seneste 7 dage • Alle filer"</string>
<string name="no_permissions_allowed" msgid="6081976856354669209">"Der ikke givet nogen tilladelser"</string>
diff --git a/PermissionController/res/values-fi/strings.xml b/PermissionController/res/values-fi/strings.xml
index 1f8678e72..b346e5837 100644
--- a/PermissionController/res/values-fi/strings.xml
+++ b/PermissionController/res/values-fi/strings.xml
@@ -195,8 +195,8 @@
<string name="approximate_image_description" msgid="938803699637069884">"Likimääräinen sijainti"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Käytä tarkkaa sijaintia"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kun tarkka sijainti ei ole päällä, sovellukset voivat nähdä likimääräisen sijaintisi"</string>
- <string name="app_permission_title" msgid="2090897901051370711">"Lupa (<xliff:g id="PERM">%1$s</xliff:g>)"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Sovellus pyytää pääsyä näihin: <xliff:g id="PERM">%1$s</xliff:g>"</string>
+ <string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>lupa"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Sovellus pyytää <xliff:g id="PERM">%1$s</xliff:g>-lupaa"</string>
<string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Tällä sovelluksella on pääsy (<xliff:g id="PERM">%1$s</xliff:g>) laitteella <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Näytä kaikki luvat, jotka <xliff:g id="APP">%1$s</xliff:g> on saanut"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Näytä kaikki sovellukset, joilla on tämä lupa"</string>
diff --git a/PermissionController/res/values-fr-rCA/strings.xml b/PermissionController/res/values-fr-rCA/strings.xml
index 711ab3a5a..8998bad3d 100644
--- a/PermissionController/res/values-fr-rCA/strings.xml
+++ b/PermissionController/res/values-fr-rCA/strings.xml
@@ -205,9 +205,9 @@
<string name="auto_revoke_label" msgid="5068393642936571656">"Retirer les autorisations si l\'application est inutilisée"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"Retirer autorisations et libérer espace"</string>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"Suspendre l\'activité appli si inutilisée"</string>
- <string name="unused_apps_label_v3" msgid="693340578642156657">"Gérer l\'application si inutilisée"</string>
+ <string name="unused_apps_label_v3" msgid="693340578642156657">"Gérer l\'appli si inutilisée"</string>
<string name="unused_apps_summary" msgid="8839466950318403115">"Retirer les autorisations, supprimer les fichiers temporaires et arrêter les notifications"</string>
- <string name="unused_apps_summary_v2" msgid="5011313200815115802">"Retirer les autorisations, supprimer les fichiers temporaires, arrêter les notifications et archiver l\'application"</string>
+ <string name="unused_apps_summary_v2" msgid="5011313200815115802">"Retirer les autorisations, supprimer les fichiers temporaires, arrêter les notifications et archiver l\'appli"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"Afin de protéger vos données, les autorisations pour cette application seront retirées si elle n\'est pas utilisée pendant quelques mois."</string>
<string name="auto_revoke_summary_with_permissions" msgid="389712086597285013">"Afin de protéger vos données, si l\'application n\'est pas utilisée pendant quelques mois, les autorisations suivantes seront supprimées : <xliff:g id="PERMS">%1$s</xliff:g>"</string>
<string name="auto_revoked_apps_page_summary" msgid="6594753657893756536">"Afin de protéger vos données, les autorisations ont été supprimées pour les applications que vous n\'avez pas utilisées depuis quelques mois."</string>
diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml
index 541c1435a..09156d094 100644
--- a/PermissionController/res/values-hi/strings.xml
+++ b/PermissionController/res/values-hi/strings.xml
@@ -407,7 +407,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/strings.xml b/PermissionController/res/values-hr/strings.xml
index bb069d1c3..46256c669 100644
--- a/PermissionController/res/values-hr/strings.xml
+++ b/PermissionController/res/values-hr/strings.xml
@@ -194,9 +194,9 @@
<string name="precise_image_description" msgid="6349638632303619872">"Točna lokacija"</string>
<string name="approximate_image_description" msgid="938803699637069884">"Približna lokacija"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"Koristi točnu lokaciju"</string>
- <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kad je točna lokacija isključena, aplikacije mogu pristupiti vašoj približnoj lokaciji"</string>
+ <string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"Kad je točna lokacija isključena, aplikacije mogu pristupati vašoj približnoj lokaciji"</string>
<string name="app_permission_title" msgid="2090897901051370711">"Dopuštenje <xliff:g id="PERM">%1$s</xliff:g>"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"Pristup aplikacije značajci \"<xliff:g id="PERM">%1$s</xliff:g>\""</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"Pristup aplikacije dopuštenju \"<xliff:g id="PERM">%1$s</xliff:g>\""</string>
<string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Pristup značajke <xliff:g id="PERM">%1$s</xliff:g> za ovu aplikaciju na uređaju <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Pogledajte sva dopuštenja aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Pogledajte sve aplikacije s tim dopuštenjem"</string>
diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml
index 73c5e0ec2..24d611e6e 100644
--- a/PermissionController/res/values-hy/strings.xml
+++ b/PermissionController/res/values-hy/strings.xml
@@ -405,7 +405,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/strings.xml b/PermissionController/res/values-in/strings.xml
index 51f0cfb7e..88d9ddc8e 100644
--- a/PermissionController/res/values-in/strings.xml
+++ b/PermissionController/res/values-in/strings.xml
@@ -407,7 +407,7 @@
<string name="role_notes_search_keywords" msgid="7710756695666744631">"catatan"</string>
<string name="role_wallet_label" msgid="3719419175656204207">"Aplikasi dompet default"</string>
<string name="role_wallet_short_label" msgid="6521288403762457452">"Aplikasi dompet"</string>
- <string name="role_wallet_description" msgid="3726535836165949838">"Aplikasi dompet dapat menyimpan kartu kredit dan kartu loyalitas, kunci mobil, serta hal lainnya untuk membantu berbagai bentuk transaksi."</string>
+ <string name="role_wallet_description" msgid="3726535836165949838">"Aplikasi dompet dapat menyimpan kartu kredit dan kartu loyalitas, kunci mobil, serta hal lain untuk membantu berbagai bentuk transaksi."</string>
<string name="role_wallet_request_title" msgid="4770217108262737093">"Setel <xliff:g id="APP_NAME">%1$s</xliff:g> sebagai aplikasi dompet default?"</string>
<string name="role_wallet_request_description" msgid="6305487425777483053">"Tidak ada izin yang diperlukan"</string>
<string name="request_role_current_default" msgid="738722892438247184">"Default saat ini"</string>
diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml
index d493b25a8..3443f9b47 100644
--- a/PermissionController/res/values-my/strings.xml
+++ b/PermissionController/res/values-my/strings.xml
@@ -407,7 +407,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>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index bd8922604..a761dfe91 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -27,7 +27,7 @@
<string name="off" msgid="1438489226422866263">"निष्क्रिय"</string>
<string name="uninstall_or_disable" msgid="4496612999740858933">"अनइन्स्टल गर्नुहोस् वा असक्षम पार्नुहोस्"</string>
<string name="app_not_found_dlg_title" msgid="6029482906093859756">"एप फेला परेन"</string>
- <string name="grant_dialog_button_deny" msgid="88262611492697192">"अनुमति नदिइयोस्"</string>
+ <string name="grant_dialog_button_deny" msgid="88262611492697192">"अनुमति नदिनुहोस्"</string>
<string name="grant_dialog_button_deny_and_dont_ask_again" msgid="1748925431574312595">"अनुमति नदिइनुहोस् र फेरि नसोध्नुहोस्"</string>
<string name="grant_dialog_button_no_upgrade" msgid="8344732743633736625">"“एप प्रयोगमा भएको बेलामा” शीर्षक कायम राख्नुहोस्"</string>
<string name="grant_dialog_button_no_upgrade_one_time" msgid="5125892775684968694">"“यस बेला मात्र” राख्नुहोस्"</string>
@@ -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>
@@ -190,7 +190,7 @@
<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>
+ <string name="app_permission_button_deny" msgid="6016454069832050300">"अनुमति नदिनुहोस्"</string>
<string name="precise_image_description" msgid="6349638632303619872">"सटीक स्थान"</string>
<string name="approximate_image_description" msgid="938803699637069884">"अनुमानित स्थान"</string>
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"सटीक लोकेसन प्रयोग गर्नुहोस्"</string>
diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml
index a31cb8e84..846caae00 100644
--- a/PermissionController/res/values-sr/strings.xml
+++ b/PermissionController/res/values-sr/strings.xml
@@ -405,10 +405,10 @@
<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>
+ <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>
<string name="request_role_dont_ask_again" msgid="3556017886029520306">"Не питај поново"</string>
diff --git a/PermissionController/res/values-te/strings.xml b/PermissionController/res/values-te/strings.xml
index 36fca2970..09b0e979e 100644
--- a/PermissionController/res/values-te/strings.xml
+++ b/PermissionController/res/values-te/strings.xml
@@ -205,7 +205,7 @@
<string name="auto_revoke_label" msgid="5068393642936571656">"యాప్‌ని ఉపయోగించకపోతే, అనుమతులను తీసివేయండి"</string>
<string name="unused_apps_label" msgid="2595428768404901064">"అనుమతులను తీసివేసి స్పేస్‌ను ఖాళీ చేయండి"</string>
<string name="unused_apps_label_v2" msgid="7058776770056517980">"యాప్‌ను ఉపయోగించకపోతే దాని యాక్టివిటీని పాజ్ చేయండి"</string>
- <string name="unused_apps_label_v3" msgid="693340578642156657">"యాప్‌ను ఉపయోగించకపోతే, మేనేజ్ చేయండి"</string>
+ <string name="unused_apps_label_v3" msgid="693340578642156657">"ఉపయోగించని యాప్‌ను మేనేజ్ చేయండి"</string>
<string name="unused_apps_summary" msgid="8839466950318403115">"అనుమతులను తీసివేయండి, తాత్కాలిక ఫైళ్లను తొలగించండి, అలాగే నోటిఫికేషన్‌లను ఆపివేయండి"</string>
<string name="unused_apps_summary_v2" msgid="5011313200815115802">"అనుమతులను తీసివేయండి, తాత్కాలిక ఫైళ్లను తొలగించండి, నోటిఫికేషన్‌లను ఆపివేయండి, యాప్‌ను ఆర్కైవ్ చేయండి"</string>
<string name="auto_revoke_summary" msgid="5867548789805911683">"మీ డేటాను సురక్షితంగా ఉంచడానికి, ఈ యాప్ కొన్ని నెలలుగా వినియోగంలో లేకుంటే, దాని అనుమతులు తీసివేయబడతాయి."</string>
diff --git a/PermissionController/res/values-v34/styles.xml b/PermissionController/res/values-v34/styles.xml
index 6ba504531..e6cc4ba79 100644
--- a/PermissionController/res/values-v34/styles.xml
+++ b/PermissionController/res/values-v34/styles.xml
@@ -123,6 +123,7 @@
<item name="android:textSize">14sp</item>
<item name="android:lineHeight">20sp</item>
<item name="android:lineSpacingMultiplier">1.25</item>
+ <item name="android:hyphenationFrequency">normalFast</item>
</style>
<style name="PermissionRationaleSectionPurposeList"
diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml
index 426d26419..bc9f84d88 100644
--- a/PermissionController/res/values-zh-rTW/strings.xml
+++ b/PermissionController/res/values-zh-rTW/strings.xml
@@ -196,7 +196,7 @@
<string name="app_permission_location_accuracy" msgid="7166912915040018669">"使用精確位置"</string>
<string name="app_permission_location_accuracy_subtitle" msgid="2654077606404987210">"精確位置關閉時,應用程式會存取你的大概位置資訊"</string>
<string name="app_permission_title" msgid="2090897901051370711">"<xliff:g id="PERM">%1$s</xliff:g>權限"</string>
- <string name="app_permission_header" msgid="2951363137032603806">"是否允許這個應用程式取得「<xliff:g id="PERM">%1$s</xliff:g>」的存取權限"</string>
+ <string name="app_permission_header" msgid="2951363137032603806">"是否允許這個應用程式存取「<xliff:g id="PERM">%1$s</xliff:g>」資訊"</string>
<string name="app_permission_header_with_device_name" msgid="7193042925656173271">"這個應用程式在<xliff:g id="DEVICE_NAME">%2$s</xliff:g>上的<xliff:g id="PERM">%1$s</xliff:g>存取權"</string>
<string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"查看「<xliff:g id="APP">%1$s</xliff:g>」的所有權限"</string>
<string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"查看具備此權限的所有應用程式"</string>
@@ -407,7 +407,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/strings.xml b/PermissionController/res/values/strings.xml
index 0ab24f962..d5429b49d 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -627,7 +627,7 @@
<string name="app_permission_header"><xliff:g id="perm" example="location">%1$s</xliff:g> access for this app</string>
<!-- Description for showing an app's permission along with device name [CHAR LIMIT=NONE] -->
- <string name="app_permission_header_with_device_name"><xliff:g id="perm" example="camera">%1$s</xliff:g> access for this app on <xliff:g id="device_name" example="tablet">%2$s</xliff:g></string>
+ <string name="app_permission_header_with_device_name"><xliff:g id="perm" example="camera">%1$s</xliff:g> access for this app on <xliff:g id="device_name" example="My Laptop">%2$s</xliff:g></string>
<!-- Text for linking to the page that shows an app's permissions [CHAR LIMIT=none] -->
<string name="app_permission_footer_app_permissions_link">See all <xliff:g id="app" example="Maps">%1$s</xliff:g> permissions</string>
@@ -805,7 +805,7 @@
<string name="denied_header">Not allowed</string>
<!-- Header to display the Permission group name along with corresponding device name [CHAR LIMIT=None] -->
- <string name="permission_group_name_with_device_name"><xliff:g id="perm_group_name" example="camera">%1$s</xliff:g> on <xliff:g id="device_name" example="tablet">%2$s</xliff:g></string>
+ <string name="permission_group_name_with_device_name"><xliff:g id="perm_group_name" example="camera">%1$s</xliff:g> on <xliff:g id="device_name" example="My Laptop">%2$s</xliff:g></string>
<!-- Text of hyperlink shown in storage_footer [CHAR LIMIT=60] -->
<string name="storage_footer_hyperlink_text">See more apps that can access all files</string>
@@ -1420,7 +1420,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and media on your device?</string>
<!-- Message shown to the user when the apps requests permission from this group. Shows in the isolated storage case. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_storage_isolated">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and media on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and media on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_contacts">Allow
@@ -1428,7 +1428,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_contacts">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your contacts on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your contacts on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
@@ -1436,7 +1436,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_location">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device_name" example="tablet">%2$s</xliff:g>\u2019s&lt;/b> location?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>\u2019s&lt;/b> location?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_location">The app will only have access to the location while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
@@ -1444,13 +1444,13 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s location?</string>
<!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgroupbackgroundrequest_device_aware_location">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device_name" example="tablet">%2$s</xliff:g>\u2019s location?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>\u2019s&lt;/b> location?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_location">This app may want to access your location all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgroupupgraderequest_location">Change location access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission to use the location while app is in foreground and background on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgroupupgraderequest_device_aware_location">Change location access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ <string name="permgroupupgraderequest_device_aware_location">Change location access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the location while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_location">This app wants to access your location all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
@@ -1459,18 +1459,18 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_nearby_devices">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to discovery and connect to nearby devices while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_nearby_devices">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to find, connect to, and determine the relative position of nearby devices? <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the app requests permission to upgrade to fine location [CHAR LIMIT=120] -->
<string name="permgrouprequest_fineupgrade">Change <xliff:g id="app_name" example="Gmail">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\u2019s location access from approximate to precise?</string>
<!-- Message shown to the user when the app requests permission to upgrade to fine location on a specific device [CHAR LIMIT=180] -->
- <string name="permgrouprequest_device_aware_fineupgrade">Change <xliff:g id="app_name" example="Gmail">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\u2019s location access on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b> from approximate to precise?</string>
+ <string name="permgrouprequest_device_aware_fineupgrade">Change <xliff:g id="app_name" example="Gmail">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>\u2019s location access on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b> from approximate to precise?</string>
<!-- Message shown to the user when the app requests permission to use coarse location [CHAR LIMIT=120] -->
<string name="permgrouprequest_coarselocation">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access this device\u2019s approximate location?</string>
<!-- Message shown to the user when the app requests permission to use coarse location for a specific device [CHAR LIMIT=180] -->
- <string name="permgrouprequest_device_aware_coarselocation">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>\u2019s approximate location?</string>
+ <string name="permgrouprequest_device_aware_coarselocation">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>\u2019s approximate location?</string>
<!-- Text for the FINE location image [CHAR LIMIT=20] -->
<string name="permgrouprequest_finelocation_imagetext">Precise</string>
<!-- Text for the COARSE location image [CHAR LIMIT=20] -->
@@ -1482,7 +1482,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_calendar">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your calendar on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your calendar on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_sms">Allow
@@ -1490,7 +1490,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_sms">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send and view SMS messages on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send and view SMS messages on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_storage">Allow
@@ -1498,7 +1498,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_storage">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos, media, and files on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos, media, and files on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_storage_q_to_s">Allow
@@ -1512,27 +1512,27 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<string name="permgrouprequest_read_media_aural">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access music and audio on this device?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgrouprequest_device_aware_read_media_aural">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access music and audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ <string name="permgrouprequest_device_aware_read_media_aural">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access music and audio on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_read_media_visual">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and videos on this device?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgrouprequest_device_aware_read_media_visual">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and videos on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ <string name="permgrouprequest_device_aware_read_media_visual">Allow &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access photos and videos on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_more_photos">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access more photos and videos on this device?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_more_photos">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access more photos and videos on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access more photos and videos on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_microphone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_microphone">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_microphone">The app will only be able to record audio while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
@@ -1540,13 +1540,13 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio?</string>
<!-- Message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgroupbackgroundrequest_device_aware_microphone">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to record audio on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_microphone">This app may want to record audio all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgroupupgraderequest_microphone">Change microphone access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgroupupgraderequest_device_aware_microphone">Change microphone access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ <string name="permgroupupgraderequest_device_aware_microphone">Change microphone access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the microphone while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_microphone">This app wants to record audio all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
@@ -1556,7 +1556,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_activityRecognition">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your physical activity on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your physical activity on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_camera">Allow
@@ -1564,7 +1564,7 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_camera">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera only while app is in foreground [CHAR LIMIT=150]-->
<string name="permgrouprequestdetail_camera">The app will only be able to take pictures and record video while you\u2019re using the app</string>
<!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
@@ -1572,13 +1572,13 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video?</string>
<!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgroupbackgroundrequest_device_aware_camera">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to take pictures and record video on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupbackgroundrequestdetail_camera">This app may want to take pictures and record video all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgroupupgraderequest_camera">Change camera access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission to use the camera while app is in foreground and background on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgroupupgraderequest_device_aware_camera">Change camera access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ <string name="permgroupupgraderequest_device_aware_camera">Change camera access for &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the camera while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=150] -->
<string name="permgroupupgraderequestdetail_camera">This app wants to take pictures and record video all the time, even when you\u2019re not using the app. <annotation id="link">Allow in settings.</annotation></string>
@@ -1587,21 +1587,21 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your phone call logs?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_calllog">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your phone call logs on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access your phone call logs on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_phone">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_phone">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to make and manage phone calls on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_sensors">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_sensors">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access sensor data about your vital signs on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=NONE] -->
<string name="permgroupupgraderequestdetail_sensors">This app wants to access sensor data about your vital signs all the time, even when you\u2019re not using the app. To make this change, <annotation id="link">go to settings.</annotation></string>
@@ -1610,20 +1610,20 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access the sensor data about your vital signs?</string>
<!-- Message shown to the user when the apps requests permission to use the bosy sensors while app is in foreground and background on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgroupbackgroundrequest_device_aware_sensors">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access the sensor data about your vital signs on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access the sensor data about your vital signs on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Subtitle of the message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background. Try to keep the link annotation at the end of the string [CHAR LIMIT=NONE] -->
<string name="permgroupbackgroundrequestdetail_sensors">To let this app access body sensor data all the time, even when you\u2019re not using the app, <annotation id="link">go to settings.</annotation></string>
<!-- Message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgroupupgraderequest_sensors">Keep allowing &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access body sensor data while app is in use?</string>
<!-- Message shown to the user when the apps requests permission to use the body sensors while app is in foreground and background on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
- <string name="permgroupupgraderequest_device_aware_sensors">Keep allowing &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access body sensor data on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b> while app is in use?</string>
+ <string name="permgroupupgraderequest_device_aware_sensors">Keep allowing &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to access body sensor data on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b> while app is in use?</string>
<!-- Message shown to the user when the apps requests permission from this group. If ever possible this should stay below 80 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 120 characters though. [CHAR LIMIT=120] -->
<string name="permgrouprequest_notifications">Allow
&lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send you notifications?</string>
<!-- Message shown to the user when the apps requests permission from this group on a specific device. If ever possible this should stay below 120 characters (assuming the parameters takes 20 characters). Don't abbreviate until the message reaches 180 characters though. [CHAR LIMIT=180] -->
<string name="permgrouprequest_device_aware_notifications">Allow
- &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send you notifications on your &lt;b><xliff:g id="device" example="tablet">%2$s</xliff:g>&lt;/b>?</string>
+ &lt;b><xliff:g id="app_name" example="Gmail">%1$s</xliff:g>&lt;/b> to send you notifications on &lt;b><xliff:g id="device_name" example="My Laptop">%2$s</xliff:g>&lt;/b>?</string>
<!-- Notification shown to the user when location permissions are auto-granted by admin policy. These are for when the admin is forcing the permission and the user cannot control it. [CHAR LIMIT=120]-->
<string name="auto_granted_permissions">Controlled permissions</string>
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
index 7810c00e3..eb78414f9 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
@@ -578,7 +578,8 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
switch (grantState) {
case PERMISSION_GRANT_STATE_GRANTED:
if (AdminRestrictedPermissionsUtils.mayAdminGrantPermission(perm.getName(),
- canAdminGrantSensorsPermissions, isManagedProfile, dpm)) {
+ group.getName(), canAdminGrantSensorsPermissions, isManagedProfile,
+ dpm)) {
perm.setPolicyFixed(true);
group.grantRuntimePermissions(false, false, new String[]{permName});
autoGrantPermissionsNotifier.onPermissionAutoGranted(permName);
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
index 2d4184fad..f2cf78ba8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java
@@ -89,7 +89,7 @@ import com.android.permissioncontroller.permission.ui.auto.GrantPermissionsAutoV
import com.android.permissioncontroller.permission.ui.model.DenyButton;
import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel;
import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModel.RequestInfo;
-import com.android.permissioncontroller.permission.ui.model.NewGrantPermissionsViewModelFactory;
+import com.android.permissioncontroller.permission.ui.model.GrantPermissionsViewModelFactory;
import com.android.permissioncontroller.permission.ui.model.Prompt;
import com.android.permissioncontroller.permission.ui.wear.GrantPermissionsWearViewHandler;
import com.android.permissioncontroller.permission.utils.ContextCompat;
@@ -152,6 +152,10 @@ public class GrantPermissionsActivity extends SettingsActivity
public static final int DIALOG_WITH_FINE_LOCATION_ONLY = 4;
public static final int DIALOG_WITH_COARSE_LOCATION_ONLY = 5;
+ // The maximum number of dialogs we will allow the same package, on the same task, to launch
+ // simultaneously
+ public static final int MAX_DIALOGS_PER_PKG_TASK = 10;
+
public static final Map<String, Integer> PERMISSION_TO_BIT_SHIFT =
Map.of(
ACCESS_COARSE_LOCATION, 0,
@@ -352,21 +356,42 @@ public class GrantPermissionsActivity extends SettingsActivity
return;
}
+ GrantPermissionsViewModelFactory factory =
+ new GrantPermissionsViewModelFactory(
+ getApplication(),
+ mTargetPackage,
+ mTargetDeviceId,
+ mRequestedPermissions,
+ mSystemRequestedPermissions,
+ mSessionId,
+ icicle);
+ mViewModel = factory.create(GrantPermissionsViewModel.class);
+
synchronized (sCurrentGrantRequests) {
mKey = new Pair<>(mTargetPackage, getTaskId());
- if (!sCurrentGrantRequests.containsKey(mKey)) {
+ GrantPermissionsActivity current = sCurrentGrantRequests.get(mKey);
+ if (current == null) {
sCurrentGrantRequests.put(mKey, this);
finishSystemStartedDialogsOnOtherTasksLocked();
} else if (mIsSystemTriggered) {
// The system triggered dialog doesn't require results. Delegate, and finish.
- sCurrentGrantRequests.get(mKey).onNewFollowerActivity(null, mRequestedPermissions);
+ current.onNewFollowerActivity(null, mRequestedPermissions, false);
finishAfterTransition();
return;
- } else if (sCurrentGrantRequests.get(mKey).mIsSystemTriggered) {
- // Normal permission requests should only merge into the system triggered dialog,
- // which has task overlay set
+ } else if (current.mIsSystemTriggered) {
+ // merge into the system triggered dialog, which has task overlay set
mDelegated = true;
- sCurrentGrantRequests.get(mKey).onNewFollowerActivity(this, mRequestedPermissions);
+ current.onNewFollowerActivity(this, mRequestedPermissions, false);
+ } else {
+ // this + current + current.mFollowerActivities
+ if ((current.mFollowerActivities.size() + 2) > MAX_DIALOGS_PER_PKG_TASK) {
+ // If there are too many dialogs for the same package, in the same task, cancel
+ finishAfterTransition();
+ return;
+ }
+ // Merge the old dialogs into the new
+ onNewFollowerActivity(current, current.mRequestedPermissions, true);
+ sCurrentGrantRequests.put(mKey, this);
}
}
@@ -389,16 +414,6 @@ public class GrantPermissionsActivity extends SettingsActivity
}
if (!mDelegated) {
- NewGrantPermissionsViewModelFactory factory =
- new NewGrantPermissionsViewModelFactory(
- getApplication(),
- mTargetPackage,
- mTargetDeviceId,
- mRequestedPermissions,
- mSystemRequestedPermissions,
- mSessionId,
- icicle);
- mViewModel = factory.create(GrantPermissionsViewModel.class);
mViewModel.getRequestInfosLiveData().observe(this, this::onRequestInfoLoad);
}
@@ -433,7 +448,7 @@ public class GrantPermissionsActivity extends SettingsActivity
// as the UI behaves differently for updates and initial creations.
if (icicle != null) {
mViewHandler.loadInstanceState(icicle);
- } else {
+ } else if (mRootView == null || mRootView.getVisibility() != View.VISIBLE) {
// Do not show screen dim until data is loaded
window.setDimAmount(0f);
}
@@ -568,20 +583,41 @@ public class GrantPermissionsActivity extends SettingsActivity
* @param newPermissions The new permissions requested in the activity
*/
private void onNewFollowerActivity(@Nullable GrantPermissionsActivity follower,
- @NonNull List<String> newPermissions) {
+ @NonNull List<String> newPermissions, boolean followerIsOlder) {
if (follower != null) {
// Ensure the list of follower activities is a stack
mFollowerActivities.add(0, follower);
follower.mViewModel = mViewModel;
+ if (followerIsOlder) {
+ follower.mDelegated = true;
+ }
}
- boolean isShowingGroup = mRootView != null && mRootView.getVisibility() == View.VISIBLE;
- List<RequestInfo> currentGroups = mViewModel.getRequestInfosLiveData().getValue();
+ // If the follower is older, examine it to find the pre-merge group
+ GrantPermissionsActivity olderActivity = follower != null && followerIsOlder
+ ? follower : this;
+ boolean isShowingGroup = olderActivity.mRootView != null
+ && olderActivity.mRootView.getVisibility() == View.VISIBLE;
+ List<RequestInfo> currentGroups =
+ olderActivity.mViewModel.getRequestInfosLiveData().getValue();
if (mPreMergeShownGroupName == null && isShowingGroup
&& currentGroups != null && !currentGroups.isEmpty()) {
mPreMergeShownGroupName = currentGroups.get(0).getGroupName();
}
+ if (isShowingGroup && mPreMergeShownGroupName != null
+ && followerIsOlder && currentGroups != null) {
+ // Load a request from the old activity
+ mRequestInfos = currentGroups;
+ showNextRequest();
+ olderActivity.mRootView.setVisibility(View.GONE);
+ }
+ if (follower != null && followerIsOlder) {
+ follower.mFollowerActivities.forEach((oldFollower) ->
+ onNewFollowerActivity(oldFollower, new ArrayList<>(), true));
+ follower.mFollowerActivities.clear();
+ }
+
if (mRequestedPermissions.containsAll(newPermissions)) {
return;
}
@@ -597,8 +633,8 @@ public class GrantPermissionsActivity extends SettingsActivity
Bundle oldState = new Bundle();
mViewModel.getRequestInfosLiveData().removeObservers(this);
mViewModel.saveInstanceState(oldState);
- NewGrantPermissionsViewModelFactory factory =
- new NewGrantPermissionsViewModelFactory(
+ GrantPermissionsViewModelFactory factory =
+ new GrantPermissionsViewModelFactory(
getApplication(),
mTargetPackage,
mTargetDeviceId,
@@ -645,19 +681,17 @@ public class GrantPermissionsActivity extends SettingsActivity
}
private void showNextRequest() {
- if (mRequestInfos.isEmpty()) {
+ if (mRequestInfos.isEmpty() || mDelegated) {
return;
}
RequestInfo info = mRequestInfos.get(0);
- // Only the top activity can receive activity results
- Activity top = mFollowerActivities.isEmpty() ? this : mFollowerActivities.get(0);
if (info.getPrompt() == Prompt.NO_UI_SETTINGS_REDIRECT) {
- mViewModel.sendDirectlyToSettings(top, info.getGroupName());
+ mViewModel.sendDirectlyToSettings(this, info.getGroupName());
return;
} else if (info.getPrompt() == Prompt.NO_UI_PHOTO_PICKER_REDIRECT) {
- mViewModel.openPhotoPicker(top);
+ mViewModel.openPhotoPicker(this);
return;
} else if (info.getPrompt() == Prompt.NO_UI_FILTER_THIS_GROUP) {
// Filtered permissions should be removed from the requested permissions list entirely,
@@ -669,7 +703,7 @@ public class GrantPermissionsActivity extends SettingsActivity
onRequestInfoLoad(mRequestInfos);
return;
} else if (info.getPrompt() == Prompt.NO_UI_HEALTH_REDIRECT) {
- mViewModel.handleHealthConnectPermissions(top);
+ mViewModel.handleHealthConnectPermissions(this);
return;
}
@@ -953,9 +987,7 @@ public class GrantPermissionsActivity extends SettingsActivity
}
if (Objects.equals(READ_MEDIA_VISUAL, name) && result == GRANTED_USER_SELECTED) {
- // Only the top activity can receive activity results
- Activity top = mFollowerActivities.isEmpty() ? this : mFollowerActivities.get(0);
- mViewModel.openPhotoPicker(top);
+ mViewModel.openPhotoPicker(this);
logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result);
return;
}
@@ -1055,14 +1087,16 @@ public class GrantPermissionsActivity extends SettingsActivity
private boolean setResultIfNeeded(int resultCode) {
if (!isResultSet()) {
List<String> oldRequestedPermissions = mRequestedPermissions;
+ mResultCode = resultCode;
removeActivityFromMap();
// If a new merge request came in before we managed to remove this activity from the
// map, then cancel the result set for now.
if (!Objects.equals(oldRequestedPermissions, mRequestedPermissions)) {
+ // Reset the result code back to its starting value of MAX_VALUE;
+ mResultCode = Integer.MAX_VALUE;
return false;
}
- mResultCode = resultCode;
if (mViewModel != null) {
mViewModel.logRequestedPermissionGroups();
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/LocationProviderInterceptDialog.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/LocationProviderInterceptDialog.java
index bd3cd1e22..88915edfd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/LocationProviderInterceptDialog.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/LocationProviderInterceptDialog.java
@@ -23,6 +23,7 @@ import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
+import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -48,18 +49,34 @@ public final class LocationProviderInterceptDialog extends FragmentActivity {
return;
}
- new AlertDialog.Builder(this)
- .setIcon(R.drawable.ic_dialog_alert_material)
- .setTitle(android.R.string.dialog_alert_title)
- .setMessage(getString(R.string.location_warning,
- Utils.getAppLabel(getPackageInfo(packageName).applicationInfo, this)))
- .setNegativeButton(R.string.ok, null)
- .setPositiveButton(R.string.location_settings, (dialog, which) ->
- startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)))
- .setOnDismissListener((dialog) -> finish())
- .show();
+ AlertDialog alertDialog =
+ new AlertDialog.Builder(this)
+ .setIcon(R.drawable.ic_dialog_alert_material)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setMessage(
+ getString(
+ R.string.location_warning,
+ Utils.getAppLabel(
+ getPackageInfo(packageName).applicationInfo, this)))
+ .setNegativeButton(R.string.ok, null)
+ .setPositiveButton(
+ R.string.location_settings,
+ (dialog, which) ->
+ startActivity(
+ new Intent(
+ Settings.ACTION_LOCATION_SOURCE_SETTINGS)))
+ .setOnDismissListener((dialog) -> finish())
+ .show();
+ try {
+ Window alertWindow = alertDialog.getWindow();
+ if (alertWindow != null) {
+ alertWindow.getDecorView().requestFocus();
+ }
+ } catch (Exception ignored) {
+ }
}
+
private @Nullable PackageInfo getPackageInfo(@NonNull String packageName) {
try {
return getPackageManager().getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
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 54a004240..b5df6f410 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt
@@ -1408,7 +1408,7 @@ class GrantPermissionsViewModel(
* @param app The current application
* @param packageName The name of the package this ViewModel represents
*/
-class NewGrantPermissionsViewModelFactory(
+class GrantPermissionsViewModelFactory(
private val app: Application,
private val packageName: String,
private val deviceId: Int,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
index 154fd0bff..d694f20f8 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.permission.ui.wear
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
@@ -25,6 +26,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Text
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.Category
@@ -76,13 +78,22 @@ internal fun WearPermissionAppsContent(
onShowSystemClick: (showSystem: Boolean) -> Unit
) {
ScrollableScreen(title = title, subtitle = subtitle, isLoading = isLoading) {
- for (category in categoryOrder) {
+ val firstItemIndex = categoryOrder.indexOfFirst { !chipsByCategory[it].isNullOrEmpty() }
+ for ((index, category) in categoryOrder.withIndex()) {
val chips = chipsByCategory[category]
if (chips.isNullOrEmpty()) {
continue
}
item {
- ListSubheader {
+ ListSubheader(
+ modifier =
+ Modifier.padding(
+ top = if (index == firstItemIndex) 0.dp else 12.dp,
+ bottom = 4.dp,
+ start = 14.dp,
+ end = 14.dp
+ )
+ ) {
Text(text = stringResource(getCategoryString(category, showAlways)))
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt
index 53d41f7f0..7e4e939b9 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt
@@ -22,6 +22,7 @@ import androidx.annotation.IntDef
import com.android.permissioncontroller.R
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit
+import java.util.Locale
object WearUtils {
@Retention(AnnotationRetention.SOURCE)
@@ -77,4 +78,8 @@ object WearUtils {
}
return Triple(lastAccessTimeFormatted, lastAccessType, lastAccessDateFormatted)
}
+
+ fun String.capitalize(): String = replaceFirstChar {
+ if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt
index bf9ebbadd..ff3eddc65 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/Chip.kt
@@ -31,10 +31,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.platform.LocalConfiguration
-import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@@ -46,7 +45,6 @@ import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.contentColorFor
-import com.android.permissioncontroller.R
/**
* This component is an alternative to [Chip], providing the following:
@@ -166,6 +164,8 @@ public fun Chip(
* This component is an alternative to [Chip], providing the following:
* - a convenient way of providing a label and a secondary label;
*/
+// Setting the color as per
+// https://source.corp.google.com/piper///depot/google3/java/com/google/android/clockwork/common/wearable/wearmaterial/button/res/color/wear_button_secondary_text_stateful.xml?q=wear_button_secondary_text_stateful
@Composable
public fun Chip(
label: String,
@@ -177,7 +177,7 @@ public fun Chip(
icon: (@Composable BoxScope.() -> Unit)? = null,
largeIcon: Boolean = false,
textColor: Color = MaterialTheme.colors.onSurface,
- secondaryTextColor: Color = colorResource(R.color.wear_material_gray_600),
+ secondaryTextColor: Color = MaterialTheme.colors.primary,
colors: ChipColors = chipDefaultColors(),
enabled: Boolean = true
) {
@@ -192,7 +192,7 @@ public fun Chip(
textAlign = if (hasSecondaryLabel || hasIcon) TextAlign.Start else TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = labelMaxLines ?: if (hasSecondaryLabel) 1 else 2,
- style = MaterialTheme.typography.button
+ style = MaterialTheme.typography.button.copy(fontWeight = FontWeight.W600)
)
}
@@ -225,10 +225,7 @@ public fun Chip(
Chip(
label = labelParam,
onClick = onClick,
- modifier =
- modifier
- .adjustChipHeightToFontScale(LocalConfiguration.current.fontScale)
- .fillMaxWidth(),
+ modifier = modifier.fillMaxWidth(),
secondaryLabel = secondaryLabelParam,
icon = icon,
colors = colors,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
index 0afbb05fe..259e1b0b2 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ListHeader.kt
@@ -21,14 +21,11 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.IntrinsicSize
-import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
@@ -38,6 +35,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.LocalContentColor
import androidx.wear.compose.material.LocalTextStyle
@@ -50,31 +48,32 @@ import androidx.wear.compose.material.MaterialTheme
* @param modifier The modifier for the [ListHeader].
* @param backgroundColor The background color to apply - typically Color.Transparent
* @param contentColor The color to apply to content.
- * @param contentPadding The spacing values to apply internally between the container and the
- * content.
* @param content Slot for [ListHeader] content, expected to be a single line of text.
*/
+
+// Styling updated to match with wear material title
+// Ref:
+// https://source.corp.google.com/h/googleplex-android/platform/superproject/main/+/main:vendor/google_clockwork_partners/libs/ClockworkCommonLibs/common/wearable/wearmaterial/preference/res/layout/wear_title_preference.xml;l=1;drc=8ebd53cbba588e8e9aa964522fb05f4f5224609e;bpv=1;bpt=0
@Composable
fun ListHeader(
modifier: Modifier = Modifier,
backgroundColor: Color = Color.Transparent,
- contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
- contentPadding: PaddingValues = ListHeaderDefaults.HeaderContentPadding,
+ contentColor: Color = MaterialTheme.colors.onBackground,
content: @Composable RowScope.() -> Unit
) {
Row(
horizontalArrangement = Arrangement.Center,
modifier =
- modifier
- .defaultMinSize(minHeight = ListHeaderDefaults.Height)
- .wrapContentSize()
- .background(backgroundColor)
- .padding(contentPadding)
- .semantics(mergeDescendants = true) { heading() }
+ modifier.wrapContentSize().background(backgroundColor).semantics(
+ mergeDescendants = true
+ ) {
+ heading()
+ }
) {
CompositionLocalProvider(
LocalContentColor provides contentColor,
- LocalTextStyle provides MaterialTheme.typography.title3,
+ LocalTextStyle provides
+ MaterialTheme.typography.title3.copy(fontWeight = FontWeight.W600),
) {
content()
}
@@ -88,8 +87,6 @@ fun ListHeader(
* @param modifier The modifier for the [ListSubheader].
* @param backgroundColor The background color to apply - typically Color.Transparent
* @param contentColor The color to apply to content.
- * @param contentPadding The spacing values to apply internally between the container and the
- * content.
* @param icon A slot for providing icon to the [ListSubheader].
* @param label A slot for providing label to the [ListSubheader].
*/
@@ -98,7 +95,6 @@ fun ListSubheader(
modifier: Modifier = Modifier,
backgroundColor: Color = Color.Transparent,
contentColor: Color = MaterialTheme.colors.onBackground,
- contentPadding: PaddingValues = ListHeaderDefaults.SubheaderContentPadding,
icon: (@Composable BoxScope.() -> Unit)? = null,
label: @Composable RowScope.() -> Unit,
) {
@@ -107,12 +103,10 @@ fun ListSubheader(
horizontalArrangement = Arrangement.Start,
modifier =
modifier
- .defaultMinSize(minHeight = ListHeaderDefaults.Height)
.height(IntrinsicSize.Min)
.fillMaxWidth()
.wrapContentSize(align = Alignment.CenterStart)
.background(backgroundColor)
- .padding(contentPadding)
.semantics(mergeDescendants = true) { heading() }
) {
CompositionLocalProvider(
@@ -130,16 +124,3 @@ fun ListSubheader(
}
}
}
-
-object ListHeaderDefaults {
- private val TopPadding = 16.dp
- private val SubheaderBottomPadding = 8.dp
- private val HeaderBottomPadding = 12.dp
- private val HorizontalPadding = 14.dp
- internal val Height = 48.dp
-
- val HeaderContentPadding =
- PaddingValues(HorizontalPadding, TopPadding, HorizontalPadding, HeaderBottomPadding)
- val SubheaderContentPadding =
- PaddingValues(HorizontalPadding, TopPadding, HorizontalPadding, SubheaderBottomPadding)
-}
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 13b8e44b7..0dceceeae 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
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -33,13 +34,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
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.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.text.style.TextAlign
@@ -47,6 +46,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.repeatOnLifecycle
import androidx.wear.compose.foundation.SwipeToDismissValue
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
@@ -63,6 +63,7 @@ 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.WearUtils.capitalize
import com.android.permissioncontroller.permission.ui.wear.elements.rotaryinput.rotaryWithScroll
import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme
@@ -124,7 +125,6 @@ fun ScrollableScreen(
}
}
-@OptIn(ExperimentalComposeUiApi::class)
@Composable
internal fun Scaffold(
showTimeText: Boolean,
@@ -139,16 +139,47 @@ internal fun Scaffold(
val screenWidth = LocalConfiguration.current.screenWidthDp
val screenHeight = LocalConfiguration.current.screenHeightDp
val scrollContentHorizontalPadding = (screenWidth * 0.052).dp
+ val titleHorizontalPadding = (screenWidth * 0.0884).dp
+ val subtitleHorizontalPadding = (screenWidth * 0.0416).dp
val scrollContentTopPadding = (screenHeight * 0.1456).dp
val scrollContentBottomPadding = (screenHeight * 0.3636).dp
+ val titleBottomPadding =
+ if (subtitle == null) {
+ 8.dp
+ } else {
+ 4.dp
+ }
+ val subtitleBottomPadding = 8.dp
+ val timeTextTopPadding =
+ if (showTimeText) {
+ 1.dp
+ } else {
+ 0.dp
+ }
+ val titlePaddingValues =
+ PaddingValues(
+ start = titleHorizontalPadding,
+ top = 4.dp,
+ bottom = titleBottomPadding,
+ end = titleHorizontalPadding
+ )
+ val subTitlePaddingValues =
+ PaddingValues(
+ start = subtitleHorizontalPadding,
+ top = 4.dp,
+ bottom = subtitleBottomPadding,
+ end = subtitleHorizontalPadding
+ )
val initialCenterIndex = 0
val centerHeightDp = Dp(LocalConfiguration.current.screenHeightDp / 2.0f)
- val initialCenterItemScrollOffset = scrollContentTopPadding + 10.dp
+ // We are adding TimeText's padding to create a smooth scrolling
+ val initialCenterItemScrollOffset = scrollContentTopPadding + timeTextTopPadding
val scrollAwayOffset = centerHeightDp - initialCenterItemScrollOffset
-
val focusRequester = remember { FocusRequester() }
val listState = remember { ScalingLazyListState(initialCenterItemIndex = initialCenterIndex) }
-
+ LaunchedEffect(title) {
+ listState.animateScrollToItem(index = 0) // Scroll to the top when triggerValue changes
+ }
WearPermissionTheme {
Scaffold(
// TODO: Use a rotary modifier from Wear Compose once Wear Compose 1.4 is landed.
@@ -162,8 +193,8 @@ internal fun Scaffold(
if (showTimeText && !isLoading) {
TimeText(
modifier =
- Modifier.scrollAway(listState, initialCenterIndex, scrollAwayOffset),
- contentPadding = PaddingValues(5.dp)
+ Modifier.scrollAway(listState, initialCenterIndex, scrollAwayOffset)
+ .padding(top = timeTextTopPadding),
)
}
},
@@ -175,6 +206,7 @@ internal fun Scaffold(
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
} else {
ScalingLazyColumn(
+ modifier = Modifier.fillMaxWidth(),
state = listState,
// Set autoCentering to null to avoid adding extra padding based on the
// content.
@@ -217,7 +249,7 @@ internal fun Scaffold(
if (titleTestTag != null) {
modifier = modifier.testTag(titleTestTag)
}
- ListHeader {
+ ListHeader(modifier = Modifier.padding(titlePaddingValues)) {
Text(
text = title,
textAlign = TextAlign.Center,
@@ -228,17 +260,18 @@ internal fun Scaffold(
}
if (subtitle != null) {
item {
- var modifier: Modifier = Modifier
+ var modifier: Modifier =
+ Modifier.align(Alignment.Center).padding(subTitlePaddingValues)
if (subtitleTestTag != null) {
modifier = modifier.testTag(subtitleTestTag)
}
AnnotatedText(
- text = subtitle,
+ text = subtitle.toString().capitalize(),
style =
MaterialTheme.typography.body2.copy(
color = MaterialTheme.colors.onSurfaceVariant
),
- modifier = modifier.fillMaxWidth(),
+ modifier = modifier
)
}
}
@@ -264,7 +297,7 @@ private fun RequestFocusOnResume(focusRequester: FocusRequester) {
internal fun dismiss(activity: Activity) {
if (activity is FragmentActivity) {
- if (!activity.getSupportFragmentManager().popBackStackImmediate()) {
+ if (!activity.supportFragmentManager.popBackStackImmediate()) {
activity.finish()
}
} else {
@@ -274,9 +307,7 @@ internal fun dismiss(activity: Activity) {
internal fun getBackStackEntryCount(activity: Activity): Int {
return if (activity is FragmentActivity) {
- activity
- .getSupportFragmentManager()
- .primaryNavigationFragment
+ activity.supportFragmentManager.primaryNavigationFragment
?.childFragmentManager
?.backStackEntryCount
?: 0
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
index 9a8a29bc3..fe1e75d67 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
@@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
@@ -142,10 +141,7 @@ public fun ToggleChip(
label = labelParam,
toggleControl = toggleControlParam,
modifier =
- modifier
- .adjustChipHeightToFontScale(LocalConfiguration.current.fontScale)
- .fillMaxWidth()
- .semantics { stateDescription = stateDescriptionSemantics },
+ modifier.fillMaxWidth().semantics { stateDescription = stateDescriptionSemantics },
appIcon = iconParam,
secondaryLabel = secondaryLabelParam,
colors = colors,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java
index 770ee6c95..4fde616e3 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/v31/AdminRestrictedPermissionsUtils.java
@@ -25,6 +25,7 @@ import android.os.UserManager;
import android.util.ArraySet;
import com.android.modules.utils.build.SdkLevel;
+import com.android.permissioncontroller.permission.utils.PermissionMapping;
/**
* A class for dealing with permissions that the admin may not grant in certain configurations.
@@ -78,7 +79,7 @@ public final class AdminRestrictedPermissionsUtils {
/**
* Returns true if the admin may grant this permission, false otherwise.
*/
- public static boolean mayAdminGrantPermission(String permission,
+ public static boolean mayAdminGrantPermission(String permission, String permissionGroup,
boolean canAdminGrantSensorsPermissions, boolean isManagedProfile,
DevicePolicyManager dpm) {
if (!SdkLevel.isAtLeastS()) {
@@ -87,7 +88,12 @@ public final class AdminRestrictedPermissionsUtils {
if (isManagedProfile && Manifest.permission.READ_SMS.equals(permission)) {
return mayManagedProfileAdminGrantReadSms(dpm);
}
- if (!ADMIN_RESTRICTED_SENSORS_PERMISSIONS.contains(permission)) {
+ boolean isAdminRestrictedSensorPermissionGroup = permissionGroup != null
+ && PermissionMapping.getPlatformPermissionNamesOfGroup(permissionGroup).stream()
+ .anyMatch(ADMIN_RESTRICTED_SENSORS_PERMISSIONS::contains);
+
+ if (!ADMIN_RESTRICTED_SENSORS_PERMISSIONS.contains(permission)
+ && !isAdminRestrictedSensorPermissionGroup) {
return true;
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
index 8804b3c29..85079eb1c 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterQsFragment.java
@@ -27,6 +27,7 @@ import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
+import android.graphics.Insets;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
@@ -41,6 +42,7 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -150,6 +152,11 @@ public class SafetyCenterQsFragment extends Fragment {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.safety_center_qs, container, false);
root.setVisibility(View.GONE);
root.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
+ root.setOnApplyWindowInsetsListener((v, w) -> {
+ final Insets insets = w.getInsets(WindowInsets.Type.systemBars());
+ v.setPadding(insets.left, insets.top, insets.right, insets.bottom);
+ return WindowInsets.CONSUMED;
+ });
View closeButton = root.findViewById(R.id.close_button);
closeButton.setOnClickListener((v) -> requireActivity().finish());
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt
new file mode 100644
index 000000000..fb9e7905c
--- /dev/null
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/AdminRestrictedPermissionsUtilsTest.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.tests.mocking.permission.utils
+
+import android.app.admin.DevicePolicyManager
+import android.platform.test.annotations.AsbSecurityTest
+import com.android.permissioncontroller.permission.utils.v31.AdminRestrictedPermissionsUtils
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.Mockito.mock
+
+@RunWith(Parameterized::class)
+class AdminRestrictedPermissionsUtilsTest(
+ private val permission: String,
+ private val group: String?,
+ private val canAdminGrantSensorsPermissions: Boolean,
+ private val expected: Boolean
+) {
+
+ private val dpm: DevicePolicyManager = mock(DevicePolicyManager::class.java)
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters(name = "{index}: validate({0}, {1}, {3}) = {4}")
+ fun primeNumbers(): List<Array<out Any?>> {
+ return listOf(
+ arrayOf("abc", "xyz", false, true),
+ arrayOf("abc", null, false, true),
+ arrayOf("android.permission.RECORD_AUDIO", "xyz", false, false),
+ arrayOf("abc", "android.permission-group.MICROPHONE", false, false),
+ arrayOf(
+ "android.permission.RECORD_AUDIO",
+ "android.permission-group.MICROPHONE",
+ false,
+ false
+ ),
+ arrayOf(
+ "android.permission.RECORD_AUDIO",
+ "android.permission-group.MICROPHONE",
+ true,
+ true
+ ),
+ )
+ }
+ }
+
+ @AsbSecurityTest(cveBugId = [308138085])
+ @Test
+ fun mayAdminGrantPermissionTest() {
+ val canGrant =
+ AdminRestrictedPermissionsUtils.mayAdminGrantPermission(
+ permission,
+ group,
+ canAdminGrantSensorsPermissions,
+ false,
+ dpm
+ )
+ assertEquals(expected, canGrant)
+ }
+}
diff --git a/SafetyCenter/Resources/res/values-in-v35/strings.xml b/SafetyCenter/Resources/res/values-in-v35/strings.xml
index 0405eb65e..fdbb8d8f9 100644
--- a/SafetyCenter/Resources/res/values-in-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-in-v35/strings.xml
@@ -24,7 +24,7 @@
<string name="privacy_sources_title" msgid="309304028326660956">"Kontrol privasi"</string>
<string name="privacy_sources_summary" msgid="2165270848857537278">"Izin, kontrol"</string>
<string name="privacy_additional_title" msgid="4239060639056083649"></string>
- <string name="private_space_title" msgid="6158245041481535879">"Ruang Pribadi"</string>
+ <string name="private_space_title" msgid="6158245041481535879">"Ruang Privasi"</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>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Ruang Privasi"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-my-v35/strings.xml b/SafetyCenter/Resources/res/values-my-v35/strings.xml
index c24860893..7478848dd 100644
--- a/SafetyCenter/Resources/res/values-my-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-my-v35/strings.xml
@@ -24,7 +24,7 @@
<string name="privacy_sources_title" msgid="309304028326660956">"ကိုယ်ရေးအချက်အလက်လုံခြုံမှု ဆက်တင်များ"</string>
<string name="privacy_sources_summary" msgid="2165270848857537278">"ခွင့်ပြုချက်များ၊ သတ်မှတ်ချက်များ"</string>
<string name="privacy_additional_title" msgid="4239060639056083649"></string>
- <string name="private_space_title" msgid="6158245041481535879">"သီးသန့်ချတ်ခန်း"</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>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"သီးသန့်နေရာ"</string>
</resources>
diff --git a/SafetyCenter/Resources/res/values-ru-v35/strings.xml b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
index 72fcee4b5..87f9e0572 100644
--- a/SafetyCenter/Resources/res/values-ru-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-ru-v35/strings.xml
@@ -24,7 +24,7 @@
<string name="privacy_sources_title" msgid="309304028326660956">"Настройки конфиденциальности"</string>
<string name="privacy_sources_summary" msgid="2165270848857537278">"Разрешения и параметры"</string>
<string name="privacy_additional_title" msgid="4239060639056083649"></string>
- <string name="private_space_title" msgid="6158245041481535879">"Личное пространство"</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>
+ <string name="private_space_search_terms" msgid="4820808478299116258">"Частное пространство"</string>
</resources>
diff --git a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt
index 532082770..f0298e35b 100644
--- a/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt
+++ b/tests/cts/permissionmultidevice/src/android/permissionmultidevice/cts/AppPermissionsTest.kt
@@ -31,7 +31,6 @@ import android.permission.flags.Flags
import android.permissionmultidevice.cts.PermissionUtils.isCddCompliantScreenSize
import android.platform.test.annotations.RequiresFlagsEnabled
import android.provider.Settings
-import android.util.Log
import android.virtualdevice.cts.common.VirtualDeviceRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -57,7 +56,6 @@ import org.junit.runner.RunWith
class AppPermissionsTest {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
private val defaultDeviceContext = instrumentation.targetContext
- private val TAG = AppPermissionsTest::class.java.simpleName
@get:Rule
var virtualDeviceRule =
@@ -84,7 +82,6 @@ class AppPermissionsTest {
assumeTrue(isCddCompliantScreenSize())
PackageManagementUtils.installPackage(APP_APK_PATH_STREAMING)
- assertTrue(isPackageInstalled())
val virtualDeviceManager =
defaultDeviceContext.getSystemService(VirtualDeviceManager::class.java)!!
@@ -119,14 +116,6 @@ class AppPermissionsTest {
openAppPermissionsScreen()
- val expectedGrantInfoMap =
- mapOf(
- "Allowed" to listOf(externalDeviceCameraText),
- "Ask every time" to emptyList(),
- "Not allowed" to listOf("Camera")
- )
- assertEquals(expectedGrantInfoMap, getGrantInfoMap())
-
clickPermissionItem(externalDeviceCameraText)
verifyPermissionMessage()
@@ -136,6 +125,15 @@ class AppPermissionsTest {
askChecked = false,
denyChecked = false
)
+
+ UiAutomatorUtils2.getUiDevice().pressBack()
+ val expectedGrantInfoMap =
+ mapOf(
+ "Allowed" to listOf(externalDeviceCameraText),
+ "Ask every time" to emptyList(),
+ "Not allowed" to listOf("Camera")
+ )
+ assertEquals(expectedGrantInfoMap, getGrantInfoMap())
}
@RequiresFlagsEnabled(
@@ -388,7 +386,6 @@ class AppPermissionsTest {
data = Uri.fromParts("package", APP_PACKAGE_NAME, null)
addCategory(Intent.CATEGORY_DEFAULT)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
eventually(
@@ -425,23 +422,6 @@ class AppPermissionsTest {
persistentDeviceId
)
- private fun isPackageInstalled(): Boolean {
- try {
- instrumentation.context.packageManager.getPackageInfo(APP_PACKAGE_NAME, 0)
- return true
- } catch (e: PackageManager.NameNotFoundException) {
- // Re-installing the package as a retry mechanism.
- Log.e(TAG, "Package=$APP_PACKAGE_NAME not found, retrying the installation")
- PackageManagementUtils.installPackage(APP_APK_PATH_STREAMING)
- }
- return try {
- instrumentation.context.packageManager.getPackageInfo(APP_PACKAGE_NAME, 0)
- true
- } catch (e: PackageManager.NameNotFoundException) {
- false
- }
- }
-
private fun getPermState(): Map<String, PermissionManager.PermissionState> =
permissionManager.getAllPermissionStates(APP_PACKAGE_NAME, persistentDeviceId)
diff --git a/tests/cts/permissionui/Android.bp b/tests/cts/permissionui/Android.bp
index cfceb3ec9..481aec778 100644
--- a/tests/cts/permissionui/Android.bp
+++ b/tests/cts/permissionui/Android.bp
@@ -70,6 +70,7 @@ android_test {
":CtsUsePermissionAppImplicitUserSelectStorage",
":CtsAppThatAccessesMicAndCameraPermission",
":CtsUsePermissionAppStorage33",
+ ":CtsAppThatMakesTwoPermRequests",
],
test_suites: [
"sts",
diff --git a/tests/cts/permissionui/AndroidTest.xml b/tests/cts/permissionui/AndroidTest.xml
index eefa0018d..9b80799c2 100644
--- a/tests/cts/permissionui/AndroidTest.xml
+++ b/tests/cts/permissionui/AndroidTest.xml
@@ -70,6 +70,7 @@
<option name="push" value="CtsUsePermissionAppImplicitUserSelectStorage.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppImplicitUserSelectStorage.apk" />
<option name="push" value="CtsAppThatAccessesMicAndCameraPermission.apk->/data/local/tmp/cts-permissionui/CtsAppThatAccessesMicAndCameraPermission.apk" />
<option name="push" value="CtsUsePermissionAppStorage33.apk->/data/local/tmp/cts-permissionui/CtsUsePermissionAppStorage33.apk" />
+ <option name="push" value="CtsAppThatMakesTwoPermRequests.apk->/data/local/tmp/cts-permissionui/CtsAppThatMakesTwoPermRequests.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
diff --git a/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/Android.bp b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/Android.bp
new file mode 100644
index 000000000..a3238a277
--- /dev/null
+++ b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsAppThatMakesTwoPermRequests",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "23",
+
+ static_libs: [
+ "kotlin-stdlib",
+ ],
+
+ srcs: [
+ "src/**/*.kt",
+ ],
+}
diff --git a/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/AndroidManifest.xml b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/AndroidManifest.xml
new file mode 100644
index 000000000..f255f2fed
--- /dev/null
+++ b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.permissionui.cts.usepermission"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.CALL_PHONE"/>
+ <uses-permission android:name="android.permission.READ_CONTACTS"/>
+
+ <application android:label="StartTwoPermissionRequests">
+ <activity android:name=".Activity1"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".Activity2" android:exported="true"/>
+ </application>
+</manifest>
diff --git a/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity1.kt b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity1.kt
new file mode 100644
index 000000000..b806496e4
--- /dev/null
+++ b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity1.kt
@@ -0,0 +1,39 @@
+/*
+ * 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 android.permissionui.cts.usepermission
+
+import android.Manifest.permission.READ_CONTACTS
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.os.Handler
+
+class Activity1 : Activity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ requestPermissions(arrayOf(READ_CONTACTS), 2)
+ }
+
+ // Once the permissions dialog is showing over this activity, trigger the next dialog, and
+ // finish
+ override fun onPause() {
+ super.onPause()
+ finish()
+ Handler().postDelayed({ startActivity(Intent(this, Activity2::class.java)) }, 1000)
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity2.kt
index 4d66e6a1b..15d40c324 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AdjustChipHeightToFontScale.kt
+++ b/tests/cts/permissionui/AppThatStartsTwoPermissionDialogs/src/android/permissionui/cts/usepermission/Activity2.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * 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.
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-package com.android.permissioncontroller.permission.ui.wear.elements
+package android.permissionui.cts.usepermission
-import androidx.compose.foundation.layout.height
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.dp
+import android.Manifest
+import android.app.Activity
+import android.os.Bundle
+import android.os.Handler
-/** Adjusts height of the chip as per the font scale. */
-public fun Modifier.adjustChipHeightToFontScale(fontScale: Float, padding: Dp = 0.dp): Modifier =
- if (fontScale > 1) {
- this.then(Modifier.height(60.dp + padding))
- } else {
- this
+class Activity2 : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ requestPermissions(arrayOf(Manifest.permission.CALL_PHONE), 3)
+ Handler().postDelayed({ finish() }, 2000)
}
+}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
index 6fc6b55a1..cc6c87999 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -96,6 +96,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
"$APK_DIRECTORY/CtsUsePermissionAppImplicitUserSelectStorage.apk"
const val APP_APK_PATH_STORAGE_33 = "$APK_DIRECTORY/CtsUsePermissionAppStorage33.apk"
const val APP_APK_PATH_OTHER_APP = "$APK_DIRECTORY/CtsDifferentPkgNameApp.apk"
+ const val APP_APK_PATH_TWO_PERM_REQUESTS =
+ "$APK_DIRECTORY/CtsAppThatMakesTwoPermRequests.apk"
const val APP_PACKAGE_NAME = "android.permissionui.cts.usepermission"
const val OTHER_APP_PACKAGE_NAME = "android.permissionui.cts.usepermissionother"
const val TEST_INSTALLER_PACKAGE_NAME = "android.permissionui.cts"
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt
index 01993adc5..9a28a19b9 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionTest23.kt
@@ -16,9 +16,13 @@
package android.permissionui.cts
+import android.content.ComponentName
+import android.content.Intent
import android.content.pm.PackageManager
import android.permission.cts.MtsIgnore
+import android.platform.test.annotations.AsbSecurityTest
import androidx.test.filters.FlakyTest
+import androidx.test.uiautomator.By
import com.android.compatibility.common.util.SystemUtil
import org.junit.Assert
import org.junit.Assume
@@ -26,7 +30,6 @@ import org.junit.Before
import org.junit.Test
/** Runtime permission behavior tests for apps targeting API 23. */
-@FlakyTest
class PermissionTest23 : BaseUsePermissionTest() {
companion object {
private const val NON_EXISTENT_PERMISSION = "permission.does.not.exist"
@@ -39,12 +42,14 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testDefault() {
// New permission model is denied by default
assertAppHasAllOrNoPermissions(false)
}
@Test
+ @FlakyTest
fun testGranted() {
grantAppPermissionsByUi(android.Manifest.permission.READ_CALENDAR)
@@ -55,6 +60,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testInteractiveGrant() {
// Start out without permission
assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
@@ -74,6 +80,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testRuntimeGroupGrantSpecificity() {
// Start out without permission
assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
@@ -90,6 +97,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testCancelledPermissionRequest() {
// Make sure we don't have the permission
assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
@@ -102,6 +110,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testRequestGrantedPermission() {
// Make sure we don't have the permission
assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
@@ -121,6 +130,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testDenialWithPrejudice() {
// Make sure we don't have the permission
assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
@@ -163,6 +173,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testGrantPreviouslyRevokedWithPrejudiceShowsPrompt() {
// Make sure we don't have the permission
assertAppHasPermission(android.Manifest.permission.READ_CALENDAR, false)
@@ -195,6 +206,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testRequestNonRuntimePermission() {
// Make sure we don't have the permission
assertAppHasPermission(android.Manifest.permission.BIND_PRINT_SERVICE, false)
@@ -208,6 +220,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testRequestNonExistentPermission() {
// Make sure we don't have the permission
assertAppHasPermission(NON_EXISTENT_PERMISSION, false)
@@ -221,6 +234,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testRequestPermissionFromTwoGroups() {
// Make sure we don't have the permissions
assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
@@ -274,6 +288,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testNullPermissionRequest() {
val permissions: Array<String?> = arrayOf(null)
val results: Array<Pair<String?, Boolean>> = arrayOf()
@@ -286,6 +301,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testNullAndRealPermission() {
// Make sure we don't have the permissions
assertAppHasPermission(android.Manifest.permission.WRITE_CONTACTS, false)
@@ -311,6 +327,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testInvalidPermission() {
// Request the permission and allow it
// Expect the permission is not granted
@@ -321,6 +338,7 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
@Test
+ @FlakyTest
fun testAskButtonSetsFlags() {
Assume.assumeFalse(
"other form factors might not support the ask button",
@@ -361,6 +379,33 @@ class PermissionTest23 : BaseUsePermissionTest() {
}
}
+ @Test
+ @AsbSecurityTest(cveBugId = [313909156])
+ fun testAppCanOnlyShowOneDialog() {
+ uninstallApp()
+ installPackage(APP_APK_PATH_TWO_PERM_REQUESTS)
+ doAndWaitForWindowTransition {
+ val intent =
+ Intent(Intent.ACTION_MAIN)
+ .setComponent(ComponentName(APP_PACKAGE_NAME, "$APP_PACKAGE_NAME.Activity1"))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ context.startActivity(intent)
+ }
+ waitFindObject(
+ By.textContains("contacts").pkg(packageManager.permissionControllerPackageName)
+ )
+ var didNotFindPhone = false
+ try {
+ waitFindObject(
+ By.textContains("phone calls").pkg(packageManager.permissionControllerPackageName),
+ 3000L
+ )
+ } catch (expected: Exception) {
+ didNotFindPhone = true
+ }
+ Assert.assertTrue("Found phone permission dialog", didNotFindPhone)
+ }
+
private fun denyPermissionRequestWithPrejudice() {
if (isTv || isWatch) {
clickPermissionRequestDontAskAgainButton()
diff --git a/tests/cts/role/Android.bp b/tests/cts/role/Android.bp
index 1768f0586..518c86467 100644
--- a/tests/cts/role/Android.bp
+++ b/tests/cts/role/Android.bp
@@ -32,6 +32,7 @@ android_test {
"androidx.test.rules",
"compatibility-device-util-axt",
"ctstestrunner-axt",
+ "Harrier",
"platform-test-annotations",
"truth",
],
@@ -46,5 +47,6 @@ android_test {
":CtsRoleTestApp",
":CtsRoleTestApp28",
":CtsRoleTestApp33WithoutInCallService",
+ ":CtsRoleTestAppForProfile",
],
}
diff --git a/tests/cts/role/AndroidTest.xml b/tests/cts/role/AndroidTest.xml
index 527ac3d32..a53fa62d0 100644
--- a/tests/cts/role/AndroidTest.xml
+++ b/tests/cts/role/AndroidTest.xml
@@ -42,6 +42,7 @@
<option name="push" value="CtsRoleTestApp.apk->/data/local/tmp/cts-role/CtsRoleTestApp.apk" />
<option name="push" value="CtsRoleTestApp28.apk->/data/local/tmp/cts-role/CtsRoleTestApp28.apk" />
<option name="push" value="CtsRoleTestApp33WithoutInCallService.apk->/data/local/tmp/cts-role/CtsRoleTestApp33WithoutInCallService.apk" />
+ <option name="push" value="CtsRoleTestAppForProfile.apk->/data/local/tmp/cts-role/CtsRoleTestAppForProfile.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/cts/role/CtsRoleTestAppForProfile/Android.bp b/tests/cts/role/CtsRoleTestAppForProfile/Android.bp
new file mode 100644
index 000000000..1d9a1e6e8
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestAppForProfile/Android.bp
@@ -0,0 +1,23 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsRoleTestAppForProfile",
+ defaults: ["mts-target-sdk-version-current"],
+ min_sdk_version: "30",
+}
diff --git a/tests/cts/role/CtsRoleTestAppForProfile/AndroidManifest.xml b/tests/cts/role/CtsRoleTestAppForProfile/AndroidManifest.xml
new file mode 100644
index 000000000..05413e55f
--- /dev/null
+++ b/tests/cts/role/CtsRoleTestAppForProfile/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?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.
+ -->
+
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.app.role.cts.appForProfile">
+
+ <application android:label="CtsRoleTestAppForProfile">
+ <!-- Browser -->
+ <activity
+ android:name=".BrowserActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="http" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
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 11ae53186..56f681388 100644
--- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
+++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java
@@ -58,13 +58,16 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.Until;
+import com.android.bedstead.harrier.BedsteadJUnit4;
+import com.android.bedstead.harrier.DeviceState;
+import com.android.bedstead.harrier.annotations.EnsureHasPrivateProfile;
+import com.android.bedstead.nene.types.OptionalBoolean;
import com.android.compatibility.common.util.DisableAnimationRule;
import com.android.compatibility.common.util.FreezeRotationRule;
import com.android.compatibility.common.util.TestUtils;
@@ -73,6 +76,7 @@ import com.android.compatibility.common.util.UiAutomatorUtils;
import org.junit.After;
import org.junit.Before;
+import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -89,7 +93,7 @@ import java.util.function.Consumer;
/**
* Tests {@link RoleManager}.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(BedsteadJUnit4.class)
public class RoleManagerTest {
private static final long TIMEOUT_MILLIS = 15 * 1000;
@@ -104,6 +108,10 @@ public class RoleManagerTest {
private static final String APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk";
private static final String APP_PACKAGE_NAME = "android.app.role.cts.app";
private static final String APP_LABEL = "CtsRoleTestApp";
+ private static final String APP_FOR_PROFILE_APK_PATH =
+ "/data/local/tmp/cts-role/CtsRoleTestAppForProfile.apk";
+ private static final String APP_FOR_PROFILE_PACKAGE_NAME = "android.app.role.cts.appForProfile";
+ private static final String APP_FOR_PROFILE = "CtsRoleTestAppForProfile";
private static final String APP_IS_ROLE_HELD_ACTIVITY_NAME = APP_PACKAGE_NAME
+ ".IsRoleHeldActivity";
private static final String APP_IS_ROLE_HELD_EXTRA_IS_ROLE_HELD = APP_PACKAGE_NAME
@@ -168,6 +176,10 @@ public class RoleManagerTest {
public ActivityTestRule<WaitForResultActivity> mActivityRule =
new ActivityTestRule<>(WaitForResultActivity.class);
+ @ClassRule
+ @Rule
+ public static final DeviceState sDeviceState = new DeviceState();
+
private String mRoleHolder;
@Before
@@ -476,13 +488,19 @@ public class RoleManagerTest {
}
private void installPackage(@NonNull String apkPath) {
- runShellCommandOrThrow(
- "pm install -r --user " + Process.myUserHandle().getIdentifier() + " " + apkPath);
+ installPackage(apkPath, Process.myUserHandle());
+ }
+
+ private void installPackage(@NonNull String apkPath, UserHandle user) {
+ runShellCommandOrThrow("pm install -r --user " + user.getIdentifier() + " " + apkPath);
}
private void uninstallPackage(@NonNull String packageName) {
- runShellCommand("pm uninstall --user " + Process.myUserHandle().getIdentifier() + " "
- + packageName);
+ uninstallPackage(packageName, Process.myUserHandle());
+ }
+
+ private void uninstallPackage(@NonNull String packageName, UserHandle user) {
+ runShellCommand("pm uninstall --user " + user.getIdentifier() + " " + packageName);
}
@Test
@@ -822,6 +840,45 @@ public class RoleManagerTest {
}
@Test
+ @RequiresFlagsEnabled(android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE)
+ @EnsureHasPrivateProfile(installInstrumentedApp = OptionalBoolean.TRUE)
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream")
+ @FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
+ public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppForPrivateSpace()
+ throws Exception {
+ // Private space is not supported on Watch right now and there are no existing plans yet.
+ if (sIsWatch) {
+ return;
+ }
+
+ UserHandle privateProfile = sDeviceState.privateProfile().userHandle();
+ assertThat(privateProfile).isNotNull();
+ installPackage(APP_APK_PATH, privateProfile);
+ installPackage(APP_FOR_PROFILE_APK_PATH, privateProfile);
+ addRoleHolderAsUser(ROLE_NAME, APP_FOR_PROFILE_PACKAGE_NAME, privateProfile);
+
+ sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
+ waitForIdle();
+
+ waitFindObject(By.hasDescendant(By.text(APP_FOR_PROFILE))).click();
+
+ waitForIdle();
+ waitFindObject(By.clickable(true).hasDescendant(By.checkable(true).checked(false))
+ .hasDescendant(By.text(APP_LABEL))).click();
+
+ assertIsRoleHolderAsUser(ROLE_NAME, APP_PACKAGE_NAME, true, privateProfile);
+
+ pressBack();
+ pressBack();
+
+ uninstallPackage(APP_PACKAGE_NAME, privateProfile);
+ uninstallPackage(APP_FOR_PROFILE_APK_PATH, privateProfile);
+ }
+
+ @Test
@FlakyTest(bugId = 288468003, detail = "CtsRoleTestCases is breaching 20min SLO")
public void openDefaultAppListAndSetDefaultAppThenIsDefaultAppInList() throws Exception {
sContext.startActivity(new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS)
@@ -1281,6 +1338,13 @@ public class RoleManagerTest {
return callWithShellPermissionIdentity(() -> sRoleManager.getRoleHolders(roleName));
}
+ @NonNull
+ private List<String> getRoleHoldersAsUser(@NonNull String roleName, UserHandle userHandle)
+ throws Exception {
+ return callWithShellPermissionIdentity(
+ () -> sRoleManager.getRoleHoldersAsUser(roleName, userHandle));
+ }
+
private void assertIsRoleHolder(@NonNull String roleName, @NonNull String packageName,
boolean shouldBeRoleHolder) throws Exception {
List<String> packageNames = getRoleHolders(roleName);
@@ -1292,12 +1356,20 @@ public class RoleManagerTest {
}
}
+ private void assertIsRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+ boolean shouldBeRoleHolder, UserHandle userHandle) throws Exception {
+ List<String> packageNames = getRoleHoldersAsUser(roleName, userHandle);
+
+ if (shouldBeRoleHolder) {
+ assertThat(packageNames).contains(packageName);
+ } else {
+ assertThat(packageNames).doesNotContain(packageName);
+ }
+ }
+
private void addRoleHolder(@NonNull String roleName, @NonNull String packageName,
boolean expectSuccess) throws Exception {
- CallbackFuture future = new CallbackFuture();
- runWithShellPermissionIdentity(() -> sRoleManager.addRoleHolderAsUser(roleName,
- packageName, 0, Process.myUserHandle(), sContext.getMainExecutor(), future));
- assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
+ addRoleHolderAsUser(roleName, packageName, Process.myUserHandle(), expectSuccess);
}
private void addRoleHolder(@NonNull String roleName, @NonNull String packageName)
@@ -1305,6 +1377,19 @@ public class RoleManagerTest {
addRoleHolder(roleName, packageName, true);
}
+ private void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+ UserHandle userHandle, boolean expectSuccess) throws Exception {
+ CallbackFuture future = new CallbackFuture();
+ runWithShellPermissionIdentity(() -> sRoleManager.addRoleHolderAsUser(roleName,
+ packageName, 0, userHandle, sContext.getMainExecutor(), future));
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(expectSuccess);
+ }
+
+ private void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+ UserHandle userHandle) throws Exception {
+ addRoleHolderAsUser(roleName, packageName, userHandle, true);
+ }
+
private void removeRoleHolder(@NonNull String roleName, @NonNull String packageName,
boolean expectSuccess) throws Exception {
CallbackFuture future = new CallbackFuture();