diff options
208 files changed, 2456 insertions, 2647 deletions
diff --git a/PermissionController/Android.bp b/PermissionController/Android.bp index 397870c20..dd1b82dc7 100644 --- a/PermissionController/Android.bp +++ b/PermissionController/Android.bp @@ -158,10 +158,10 @@ android_library { "androidx.compose.runtime_runtime", "androidx.compose.runtime_runtime-livedata", "androidx.compose.ui_ui", - "androidx.wear.compose_compose-material", "androidx.wear.compose_compose-material3", "android.content.pm.flags-aconfig-java-export", "android.os.flags-aconfig-java-export", + "wear-permission-components", ], lint: { diff --git a/PermissionController/OWNERS b/PermissionController/OWNERS index 5a58ec2f5..aceac6afa 100644 --- a/PermissionController/OWNERS +++ b/PermissionController/OWNERS @@ -17,6 +17,7 @@ per-file res/** = file:platform/packages/modules/Permission:/SafetyCenter/OWNERS # For Wear related changes per-file WEAR_OWNERS = file:/PermissionController/WEAR_OWNERS +per-file wear-permission-components/** = file:/PermissionController/WEAR_OWNERS per-file src/com/android/permissioncontroller/permission/ui/wear/** = file:/PermissionController/WEAR_OWNERS per-file src/com/android/permissioncontroller/role/ui/wear/** = file:/PermissionController/WEAR_OWNERS per-file src/com/android/permissioncontroller/incident/wear/** = file:/PermissionController/WEAR_OWNERS diff --git a/PermissionController/lint-baseline.xml b/PermissionController/lint-baseline.xml index be77a0d18..b1570d0b7 100644 --- a/PermissionController/lint-baseline.xml +++ b/PermissionController/lint-baseline.xml @@ -1,16 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01"> - - <issue - id="NewApi" - message="Class requires API level 34 (current min is 31): `android.app.AppOpsManager.OnOpNotedListener`" - errorLine1=" AppOpsManager.OnOpNotedListener," - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt" - line="46" - column="5"/> - </issue> +<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" + variant="all" version="8.4.0-alpha01"> <issue id="NewApi" @@ -20,7 +10,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="504" - column="31"/> + column="31" /> </issue> <issue @@ -31,7 +21,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="505" - column="34"/> + column="34" /> </issue> <issue @@ -42,7 +32,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="509" - column="41"/> + column="41" /> </issue> <issue @@ -53,7 +43,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="513" - column="41"/> + column="41" /> </issue> <issue @@ -64,7 +54,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="515" - column="59"/> + column="59" /> </issue> <issue @@ -75,7 +65,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="518" - column="42"/> + column="42" /> </issue> <issue @@ -86,7 +76,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="519" - column="42"/> + column="42" /> </issue> <issue @@ -97,7 +87,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="521" - column="18"/> + column="18" /> </issue> <issue @@ -108,7 +98,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionFragment.java" line="522" - column="29"/> + column="29" /> </issue> <issue @@ -119,7 +109,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="709" - column="31"/> + column="31" /> </issue> <issue @@ -130,7 +120,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="710" - column="34"/> + column="34" /> </issue> <issue @@ -141,7 +131,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="714" - column="41"/> + column="41" /> </issue> <issue @@ -152,7 +142,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="718" - column="41"/> + column="41" /> </issue> <issue @@ -163,7 +153,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="720" - column="59"/> + column="59" /> </issue> <issue @@ -174,7 +164,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="722" - column="67"/> + column="67" /> </issue> <issue @@ -185,7 +175,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="722" - column="42"/> + column="42" /> </issue> <issue @@ -196,7 +186,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="724" - column="18"/> + column="18" /> </issue> <issue @@ -207,7 +197,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionFragment.java" line="725" - column="29"/> + column="29" /> </issue> <issue @@ -218,7 +208,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionsFragment.java" line="159" - column="35"/> + column="35" /> </issue> <issue @@ -229,7 +219,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/AppPermissionsFragment.java" line="367" - column="35"/> + column="35" /> </issue> <issue @@ -240,7 +230,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="463" - column="31"/> + column="31" /> </issue> <issue @@ -251,7 +241,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="464" - column="34"/> + column="34" /> </issue> <issue @@ -262,7 +252,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="468" - column="41"/> + column="41" /> </issue> <issue @@ -273,7 +263,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="472" - column="41"/> + column="41" /> </issue> <issue @@ -284,7 +274,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="474" - column="59"/> + column="59" /> </issue> <issue @@ -295,7 +285,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="476" - column="67"/> + column="67" /> </issue> <issue @@ -306,7 +296,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="476" - column="42"/> + column="42" /> </issue> <issue @@ -317,7 +307,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="478" - column="18"/> + column="18" /> </issue> <issue @@ -328,7 +318,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java" line="479" - column="29"/> + column="29" /> </issue> <issue @@ -339,7 +329,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt" line="1059" - column="45"/> + column="45" /> </issue> <issue @@ -350,7 +340,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt" line="48" - column="74"/> + column="74" /> </issue> <issue @@ -361,7 +351,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/data/HibernatedPackagesLiveData.kt" line="51" - column="44"/> + column="44" /> </issue> <issue @@ -372,7 +362,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/IssueCardAnimator.kt" line="47" - column="37"/> + column="37" /> </issue> <issue @@ -383,7 +373,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt" line="653" - column="29"/> + column="29" /> </issue> <issue @@ -394,7 +384,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt" line="662" - column="18"/> + column="18" /> </issue> <issue @@ -405,7 +395,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt" line="1689" - column="48"/> + column="48" /> </issue> <issue @@ -416,7 +406,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt" line="140" - column="72"/> + column="72" /> </issue> <issue @@ -427,7 +417,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightPackageInfo.kt" line="140" - column="62"/> + column="62" /> </issue> <issue @@ -438,7 +428,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="288" - column="19"/> + column="19" /> </issue> <issue @@ -449,7 +439,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="291" - column="48"/> + column="48" /> </issue> <issue @@ -460,7 +450,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="291" - column="30"/> + column="30" /> </issue> <issue @@ -471,7 +461,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="292" - column="30"/> + column="30" /> </issue> <issue @@ -482,7 +472,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="292" - column="39"/> + column="39" /> </issue> <issue @@ -493,7 +483,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="298" - column="5"/> + column="5" /> </issue> <issue @@ -504,7 +494,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="298" - column="12"/> + column="12" /> </issue> <issue @@ -515,7 +505,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="301" - column="34"/> + column="34" /> </issue> <issue @@ -526,7 +516,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt" line="308" - column="13"/> + column="13" /> </issue> <issue @@ -537,7 +527,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt" line="110" - column="21"/> + column="21" /> </issue> <issue @@ -548,7 +538,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/MoreIssuesCardAnimator.kt" line="110" - column="46"/> + column="46" /> </issue> <issue @@ -559,7 +549,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/PermissionAppsFragment.java" line="114" - column="35"/> + column="35" /> </issue> <issue @@ -570,7 +560,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/television/PermissionAppsFragment.java" line="365" - column="35"/> + column="35" /> </issue> <issue @@ -581,7 +571,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/PermissionAppsViewModel.kt" line="100" - column="43"/> + column="43" /> </issue> <issue @@ -592,7 +582,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java" line="521" - column="43"/> + column="43" /> </issue> <issue @@ -603,7 +593,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java" line="521" - column="75"/> + column="75" /> </issue> <issue @@ -614,7 +604,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java" line="522" - column="48"/> + column="48" /> </issue> <issue @@ -625,7 +615,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java" line="522" - column="24"/> + column="24" /> </issue> <issue @@ -636,7 +626,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java" line="85" - column="42"/> + column="42" /> </issue> <issue @@ -647,7 +637,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java" line="97" - column="34"/> + column="34" /> </issue> <issue @@ -658,7 +648,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java" line="141" - column="73"/> + column="73" /> </issue> <issue @@ -669,7 +659,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java" line="146" - column="34"/> + column="34" /> </issue> <issue @@ -680,7 +670,7 @@ <location file="packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/safetycenter/service/SafetyCenterBackgroundRefreshJobService.java" line="152" - column="29"/> + column="29" /> </issue> </issues>
\ No newline at end of file diff --git a/PermissionController/res/layout-v35/nav_host_fragment.xml b/PermissionController/res/layout-v35/nav_host_fragment.xml new file mode 100644 index 000000000..5c2850b7a --- /dev/null +++ b/PermissionController/res/layout-v35/nav_host_fragment.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2025 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + + <fragment + android:id="@+id/nav_host_fragment" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:defaultNavHost="true" /> + +</androidx.constraintlayout.widget.ConstraintLayout> diff --git a/PermissionController/res/values-af/strings.xml b/PermissionController/res/values-af/strings.xml index 9267438f9..10e7b627c 100644 --- a/PermissionController/res/values-af/strings.xml +++ b/PermissionController/res/values-af/strings.xml @@ -202,6 +202,10 @@ <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 apps met hierdie toestemming"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <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 app nie gebruik word nie"</string> diff --git a/PermissionController/res/values-am/strings.xml b/PermissionController/res/values-am/strings.xml index 1cbb312af..fee1cc54a 100644 --- a/PermissionController/res/values-am/strings.xml +++ b/PermissionController/res/values-am/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"የረዳት ማይክሮፎን አጠቃቀምን አሳይ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ሥራ ላይ ያልዋሉ የመተግበሪያ ቅንብሮች"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"መተግበሪያ ጥቅም ላይ ካልዋለ ፈቃዶችን አስወግድ"</string> diff --git a/PermissionController/res/values-ar-v33/strings.xml b/PermissionController/res/values-ar-v33/strings.xml index b85d9f90a..3c86f5ffd 100644 --- a/PermissionController/res/values-ar-v33/strings.xml +++ b/PermissionController/res/values-ar-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"المزيد من التنبيهات"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"التنبيهات التي تم إغلاقها"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{التوسيع لعرض تنبيه واحد إضافي}zero{التوسيع لعرض # تنبيه إضافي}two{التوسيع لعرض تنبيهين إضافيَين}few{التوسيع لعرض # تنبيهات إضافية}many{التوسيع لعرض # تنبيهًا إضافيًا}other{التوسيع لعرض # تنبيه إضافي}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"تصغير"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"تنبيه: <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"اكتمل الإجراء"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"التحقّق من الإعدادات التي يمكن أن تعزّز حماية جهازك"</string> diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml index da4f5fcd3..bc573dcd5 100644 --- a/PermissionController/res/values-ar/strings.xml +++ b/PermissionController/res/values-ar/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"إذن \"<xliff:g id="PERM">%1$s</xliff:g>\" لهذا التطبيق على \"<xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"عرض أذونات استخدام ميكروفون \"مساعد Google\""</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"إعدادات التطبيقات غير المُستخدَمة"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"إزالة الأذونات في حال عدم استخدام التطبيق"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"الإعداد محظور"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"للحفاظ على أمانك، هذا الإعداد غير متوفِّر حاليًا."</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"لا يتوفّر هذا الإجراء أثناء إجراء مكالمة هاتفية"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n يطلب المخادِعون غالبًا هذا النوع من الإجراءات أثناء المكالمات الهاتفية، لذا تم حظره لحماية بياناتك. إذا طلبَ منك شخص غير معروف اتّخاذ هذا الإجراء، قد يكون ذلك عملية خداع."</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"لا يُسمح للتطبيقات بتثبيت تطبيقات أخرى أثناء إجراء مكالمة هاتفية."</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"لا يُسمح لأي تطبيق بالوصول إلى خدمة مخصّصة لتسهيل الاستخدام أثناء إجراء مكالمة هاتفية."</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"لا يُسمح بتفعيل هذه الإعدادات أثناء إجراء مكالمة هاتفية."</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"تم منع التطبيق من الوصول إلى <xliff:g id="PERMISSION_NAME">%1$s</xliff:g>"</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"طلب التطبيق أحد أذونات الوصول إلى المعلومات الحساسة، ما قد يعرّض معلوماتك الشخصية والمالية للخطر.<xliff:g id="ID_1"><br><br></xliff:g>من المحتمل ألا يعمل التطبيق بشكل صحيح إذا لم يحصل على هذا الإذن المقيَّد. <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>مزيد من المعلومات حول كيفية منح الأذونات</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"لم يُسمَح للتطبيق بأن يكون <xliff:g id="ROLE_NAME">%1$s</xliff:g> التلقائي"</string> diff --git a/PermissionController/res/values-as/strings.xml b/PermissionController/res/values-as/strings.xml index 5ec136613..ca28a1d28 100644 --- a/PermissionController/res/values-as/strings.xml +++ b/PermissionController/res/values-as/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"সহায়ক মাইক্ৰ’ফ’নৰ ব্যৱহাৰ দেখুৱাওক"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ব্যৱহাৰ নকৰা এপৰ ছেটিং"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"যদি এপ্টো ব্যৱহাৰ কৰা নাই অনুমতিসমূহ আঁতৰাওক"</string> diff --git a/PermissionController/res/values-az/strings.xml b/PermissionController/res/values-az/strings.xml index a630b9c27..fcd23f01e 100644 --- a/PermissionController/res/values-az/strings.xml +++ b/PermissionController/res/values-az/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> cihazında bu tətbiq üçün <xliff:g id="PERM">%1$s</xliff:g> girişi"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Bütün <xliff:g id="APP">%1$s</xliff:g> icazələrinə baxın"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu icazəyə sahib olan bütün tətbiqlərə baxın"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistent üçün mikrofon istifadəsini göstərin"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"İstifadə edilməyən tətbiq ayarları"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Tətbiq işlənməyəndə icazə ləğv edilsin"</string> diff --git a/PermissionController/res/values-b+sr+Latn/strings.xml b/PermissionController/res/values-b+sr+Latn/strings.xml index 4b1d9c287..275dfce8c 100644 --- a/PermissionController/res/values-b+sr+Latn/strings.xml +++ b/PermissionController/res/values-b+sr+Latn/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Ova aplikacija ima pristup za: <xliff:g id="PERM">%1$s</xliff:g> na uređaju <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Prikaži sve dozvole za: <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Prikaži sve aplikacije sa ovom dozvolom"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Prikaži kako Pomoćnik koristi mikrofon"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Podešavanja nekorišćenih aplikacija"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni dozvole ako se aplikacija ne koristi"</string> diff --git a/PermissionController/res/values-be-v33/strings.xml b/PermissionController/res/values-be-v33/strings.xml index ef1c1e6d1..0742aa8d7 100644 --- a/PermissionController/res/values-be-v33/strings.xml +++ b/PermissionController/res/values-be-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Іншыя абвесткі"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Адхіленыя абвесткі"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Разгарніце, каб убачыць яшчэ адну абвестку}one{Разгарніце, каб убачыць яшчэ # абвестку}few{Разгарніце, каб убачыць яшчэ # абвесткі}many{Разгарніце, каб убачыць яшчэ # абвестак}other{Разгарніце, каб убачыць яшчэ # абвесткі}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Згарнуць"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Абвестка. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Дзеянне завершана"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Праверце налады, якія могуць павысіць бяспеку вашай прылады"</string> diff --git a/PermissionController/res/values-be/strings.xml b/PermissionController/res/values-be/strings.xml index ed0c0ea0c..257045bed 100644 --- a/PermissionController/res/values-be/strings.xml +++ b/PermissionController/res/values-be/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Дазвол \"<xliff:g id="PERM">%1$s</xliff:g>\" для гэтай праграмы на прыладзе \"<xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Паказваць выкарыстанне мікрафона памочнікам"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Налады неактыўных праграм"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Выдаляць дазволы, калі праграма не выкарыстоўваецца"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"Налада з абмежаваным доступам"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"У мэтах бяспекі гэта налада цяпер недаступная."</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"Дзеянне недаступнае падчас тэлефоннага выкліку"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n У тэлефонных размовах махляры часта просяць усталяваць праграмы, таму ў мэтах бяспекі мы блакіруем такія дзеянні. Запыт ад невядомай вам асобы выканаць падобнае дзеянне можа расцэньвацца як махлярства."</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"Падчас тэлефоннага выкліку забараняецца даваць дазвол праграмам усталёўваць іншыя праграмы."</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"Падчас тэлефоннага выкліку забараняецца даваць праграмам доступ да спецыяльных магчымасцей."</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"Падчас тэлефоннага выкліку забараняецца ўключаць гэту наладу."</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"Праграме адмоўлена ў дазволе \"<xliff:g id="PERMISSION_NAME">%1$s</xliff:g>\""</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"Праграма запытала дазвол на доступ да канфідэнцыяльнай інфармацыі. Калі вы яго дасце, ваша асабістая і фінансавая інфармацыя можа аказацца ў небяспецы.<xliff:g id="ID_1"><br><br></xliff:g>Магчыма, без гэтага абмежаванага дазволу праграма не будзе працаваць належным чынам. <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>Даведацца, як дазволіць доступ</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"Праграме адмоўлена ў дазволе стандартна выконваць наступную ролю: <xliff:g id="ROLE_NAME">%1$s</xliff:g>"</string> diff --git a/PermissionController/res/values-bg/strings.xml b/PermissionController/res/values-bg/strings.xml index b6c019624..e5e2ec131 100644 --- a/PermissionController/res/values-bg/strings.xml +++ b/PermissionController/res/values-bg/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Достъп до <xliff:g id="PERM">%1$s</xliff:g> на <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Показване на употребата на микрофона за Асистент"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Настройки за неизползваните приложения"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Премахване на разрешенията, ако приложението не се използва"</string> diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml index a1dc63ec2..ce70aa4e8 100644 --- a/PermissionController/res/values-bn/strings.xml +++ b/PermissionController/res/values-bn/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant-এর মাইক্রোফোন ব্যবহার সম্পর্কিত ডেটা দেখুন"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ব্যবহার করা হয়নি এমন অ্যাপ সেটিংস"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"অ্যাপ ব্যবহার করা না হলে সেটি থেকে অনুমতি প্রত্যাহার করে নিন"</string> diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml index f89c78760..9f4a12a50 100644 --- a/PermissionController/res/values-bs/strings.xml +++ b/PermissionController/res/values-bs/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Pristup aplikaciji \"<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">"Prikaži sva odobrenja aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Prikaži sve aplikacije s ovim odobrenjem"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Prikaži korištenje mikrofona asistenta"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Postavke za nekorištene aplikacije"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni odobrenja ako se aplikacija ne koristi"</string> diff --git a/PermissionController/res/values-ca/strings.xml b/PermissionController/res/values-ca/strings.xml index 67b3b63ff..48cf957d1 100644 --- a/PermissionController/res/values-ca/strings.xml +++ b/PermissionController/res/values-ca/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Accés de <xliff:g id="PERM">%1$s</xliff:g> a aquesta aplicació (<xliff:g id="DEVICE_NAME">%2$s</xliff:g>)"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Mostra tots els permisos per a <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostra totes les aplicacions que tenen aquest permís"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostra l\'ús del micròfon de l\'Assistent"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuració d\'aplicació no utilitzada"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Suprimeix els permisos si no s\'utilitza l\'aplicació"</string> diff --git a/PermissionController/res/values-cs-v33/strings.xml b/PermissionController/res/values-cs-v33/strings.xml index e46488c6f..628424d1c 100644 --- a/PermissionController/res/values-cs-v33/strings.xml +++ b/PermissionController/res/values-cs-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Další upozornění"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Zavřená upozornění"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Rozbalením zobrazíte jedno další upozornění}few{Rozbalením zobrazíte # další upozornění}many{Rozbalením zobrazíte # dalšího upozornění}other{Rozbalením zobrazíte # dalších upozornění}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Sbalit"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Upozornění. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Akce dokončena"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Zkontrolujte nastavení, která mohou zvýšit ochranu vašeho zařízení"</string> diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml index eaf2b1041..582071f3c 100644 --- a/PermissionController/res/values-cs/strings.xml +++ b/PermissionController/res/values-cs/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Přístup k <xliff:g id="PERM">%1$s</xliff:g> pro tuto aplikaci v zařízení <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobrazit všechna oprávnění aplikace <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Zobrazit všechny aplikace s tímto oprávněním"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Zobrazit používání mikrofonu asistentem"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavení nepoužívaných aplikací"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Odebrat oprávnění, pokud se aplikace nepoužívá"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"Blokované nastavení"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"Z důvodu vaší bezpečnosti toto nastavení momentálně není dostupné."</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"Akce není během telefonního hovoru k dispozici"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n O tento typ akce během hovorů často žádají podvodníci. Kvůli vaší ochraně je proto blokována. Pokud vás k této akci navádí někdo, koho neznáte, může se jednat o podvod."</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"Během telefonního hovoru nelze aplikacím povolit instalovat další aplikace."</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"Během telefonního hovoru aplikacím přístup k funkcím pro usnadnění přístup povolit nelze."</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"Během telefonního hovoru toto nastavení povolit nelze."</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"Aplikaci byl odepřen přístup k oprávnění <xliff:g id="PERMISSION_NAME">%1$s</xliff:g>"</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"Aplikace požádala o přístup k citlivému oprávnění, které může ohrozit vaše osobní a finanční údaje.<xliff:g id="ID_1"><br><br></xliff:g>Je možné, že aplikace bez tohoto oprávnění nebude fungovat správně. <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>Jak povolit přístup</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"Aplikaci byla odepřena role výchozí <xliff:g id="ROLE_NAME">%1$s</xliff:g>"</string> diff --git a/PermissionController/res/values-da/strings.xml b/PermissionController/res/values-da/strings.xml index 8965558f5..c5df3e499 100644 --- a/PermissionController/res/values-da/strings.xml +++ b/PermissionController/res/values-da/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"adgang til <xliff:g id="PERM">%1$s</xliff:g> for denne app på <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Se alle tilladelser for <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Se alle apps med denne tilladelse"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Vis brug af Assistent-mikrofonen"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ubrugte appindstillinger"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Fjern tilladelser, hvis appen ikke bruges"</string> diff --git a/PermissionController/res/values-de/strings.xml b/PermissionController/res/values-de/strings.xml index 57a6657a2..886b75834 100644 --- a/PermissionController/res/values-de/strings.xml +++ b/PermissionController/res/values-de/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g>-Zugriff für diese App auf dem <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Alle Berechtigungen der App „<xliff:g id="APP">%1$s</xliff:g>“ anzeigen"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Alle Apps mit dieser Berechtigung anzeigen"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Nutzung der Berechtigung \"Mikrofon\" für Assistant anzeigen"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nicht verwendete App-Einstellungen"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Berechtigungen entfernen, wenn die App nicht verwendet wird"</string> diff --git a/PermissionController/res/values-el/strings.xml b/PermissionController/res/values-el/strings.xml index 8c5002324..240f7277f 100644 --- a/PermissionController/res/values-el/strings.xml +++ b/PermissionController/res/values-el/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Πρόσβαση στην άδεια <xliff:g id="PERM">%1$s</xliff:g> για αυτή την εφαρμογή στη συσκευή <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Εμφάνιση χρήσης μικροφώνου βοηθού"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ρυθμίσεις μη χρησιμοποιούμενων εφαρμογών"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Καταργήστε τις άδειες, εάν η εφαρμογή δεν χρησιμοποιείται."</string> diff --git a/PermissionController/res/values-en-rAU/strings.xml b/PermissionController/res/values-en-rAU/strings.xml index b6ebb1439..e5e95f4e8 100644 --- a/PermissionController/res/values-en-rAU/strings.xml +++ b/PermissionController/res/values-en-rAU/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> access for this app on <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string> diff --git a/PermissionController/res/values-en-rCA/strings.xml b/PermissionController/res/values-en-rCA/strings.xml index dd24b181a..8b657acf3 100644 --- a/PermissionController/res/values-en-rCA/strings.xml +++ b/PermissionController/res/values-en-rCA/strings.xml @@ -202,6 +202,8 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> access for this app on <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string> + <string name="app_permission_info_button" msgid="8973692370208562556">"Information"</string> + <string name="app_permission_settings_button" msgid="4582916817451973752">"Settings"</string> <string name="assistant_mic_label" msgid="1011432357152323896">"Show assistant microphone usage"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string> diff --git a/PermissionController/res/values-en-rGB/strings.xml b/PermissionController/res/values-en-rGB/strings.xml index 27aad5e69..242828ffc 100644 --- a/PermissionController/res/values-en-rGB/strings.xml +++ b/PermissionController/res/values-en-rGB/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> access for this app on <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string> diff --git a/PermissionController/res/values-en-rIN/strings.xml b/PermissionController/res/values-en-rIN/strings.xml index 27aad5e69..242828ffc 100644 --- a/PermissionController/res/values-en-rIN/strings.xml +++ b/PermissionController/res/values-en-rIN/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> access for this app on <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"See all <xliff:g id="APP">%1$s</xliff:g> permissions"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"See all apps with this permission"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Show Assistant microphone usage"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Unused app settings"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remove permissions if app isn’t used"</string> diff --git a/PermissionController/res/values-es-rUS/strings.xml b/PermissionController/res/values-es-rUS/strings.xml index 1dfed45f7..6acc5a959 100644 --- a/PermissionController/res/values-es-rUS/strings.xml +++ b/PermissionController/res/values-es-rUS/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acceso a <xliff:g id="PERM">%1$s</xliff:g> para esta app en <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos los permisos de <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas las apps que tienen este permiso"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar el uso del micrófono del Asistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuración de apps sin usar"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Quitar los permisos si la app no se usa"</string> diff --git a/PermissionController/res/values-es/strings.xml b/PermissionController/res/values-es/strings.xml index eb54a9e1c..05b24e718 100644 --- a/PermissionController/res/values-es/strings.xml +++ b/PermissionController/res/values-es/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acceso de <xliff:g id="PERM">%1$s</xliff:g> a esta aplicación en <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todos los permisos de <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas las aplicaciones con este permiso"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar el uso del micrófono del Asistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ajustes de aplicaciones sin usar"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos si la aplicación no se usa"</string> diff --git a/PermissionController/res/values-et-v33/strings.xml b/PermissionController/res/values-et-v33/strings.xml index d7adc10a0..56dd683ca 100644 --- a/PermissionController/res/values-et-v33/strings.xml +++ b/PermissionController/res/values-et-v33/strings.xml @@ -33,7 +33,7 @@ <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Ahenda"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Hoiatus. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Toiming on lõpetatud"</string> - <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Kontrollige seadeid, mis võivad teie seadme kaitset tõhusamaks muuta"</string> + <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Kontrollige seadeid, mis võivad teie seadme kaitset tõhusamaks muuta."</string> <string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Turvalisuse ja privaatsuse kiirseaded"</string> <string name="safety_center_qs_close_button" msgid="1352313308176244599">"Sule"</string> <string name="safety_center_qs_expand_action" msgid="2193190557696484169">"Laienda ja kuva valikud"</string> diff --git a/PermissionController/res/values-et/strings.xml b/PermissionController/res/values-et/strings.xml index f7036cd77..55c147f99 100644 --- a/PermissionController/res/values-et/strings.xml +++ b/PermissionController/res/values-et/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> juurdepääs sellele rakendusele seadmes <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Kuva rakenduse <xliff:g id="APP">%1$s</xliff:g> kõik load"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Kuva kõik selle loaga rakendused"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Kuva assistendi mikrofoni kasutamine"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Kasutamata rakenduse seaded"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Eemalda load, kui rakendust ei kasutata"</string> @@ -361,7 +365,8 @@ <string name="role_browser_description" msgid="3465253637499842671">"Rakendused, mis võimaldavad juurdepääsu internetile ja kuvavad puudutatavaid linke"</string> <string name="role_browser_request_title" msgid="2895200507835937192">"Kas määrata rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> vaikebrauseriks?"</string> <string name="role_browser_request_description" msgid="5888803407905985941">"Lube ei ole vaja"</string> - <string name="role_dialer_label" msgid="1100224146343237968">"Telefoni vaikerakendus"</string> + <!-- no translation found for role_dialer_label (1100224146343237968) --> + <skip /> <string name="role_dialer_short_label" msgid="7186888549465352489">"Telefonirakendus"</string> <string name="role_dialer_description" msgid="8768708633696539612">"Rakendused, mis võimaldavad teil seadmes telefonikõnesid teha ja vastu võtta"</string> <string name="role_dialer_request_title" msgid="5959618560705912058">"Kas soovite määrata rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> telefoni vaikerakenduseks?"</string> diff --git a/PermissionController/res/values-eu/strings.xml b/PermissionController/res/values-eu/strings.xml index 01b1924ed..a89ff9025 100644 --- a/PermissionController/res/values-eu/strings.xml +++ b/PermissionController/res/values-eu/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> erabiltzeko baimena aplikazio honetarako <xliff:g id="DEVICE_NAME">%2$s</xliff:g> gailuan"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ikusi <xliff:g id="APP">%1$s</xliff:g> aplikazioaren baimen guztiak"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ikusi baimen hau duten aplikazio guztiak"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Erakutsi laguntzaileak mikrofonoa erabiltzeko duen baimena"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Erabili gabeko aplikazioen ezarpenak"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Kendu baimenak aplikazioa erabiltzen ez bada"</string> diff --git a/PermissionController/res/values-fa-watch/strings.xml b/PermissionController/res/values-fa-watch/strings.xml index b602b38f3..16acde24b 100644 --- a/PermissionController/res/values-fa-watch/strings.xml +++ b/PermissionController/res/values-fa-watch/strings.xml @@ -16,7 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="grant_dialog_button_deny_dont_ask_again" msgid="5709879604352260492">"مجاز نیست، دیگر سؤال نشود"</string> + <string name="grant_dialog_button_deny_dont_ask_again" msgid="5709879604352260492">"مجاز نیست، دوباره پرسیده نشود"</string> <string name="current_permission_template" msgid="6634462553790549887">"<xliff:g id="CURRENT_PERMISSION_INDEX">%1$s</xliff:g> / <xliff:g id="PERMISSION_COUNT">%2$s</xliff:g>"</string> <string name="preference_show_system_apps" msgid="1055740303992024300">"نمایش برنامههای سیستم"</string> <string name="permission_summary_enforced_by_policy" msgid="2352478756952948019">"امکان تغییر نیست"</string> diff --git a/PermissionController/res/values-fa/strings.xml b/PermissionController/res/values-fa/strings.xml index 56e2b3e65..9da73c13f 100644 --- a/PermissionController/res/values-fa/strings.xml +++ b/PermissionController/res/values-fa/strings.xml @@ -75,7 +75,7 @@ <string name="app_disable_dlg_positive" msgid="7418444149981904940">"غیرفعال کردن برنامه"</string> <string name="app_disable_dlg_text" msgid="3126943217146120240">"اگر این برنامه را غیرفعال کنید، ممکن است Android و سایر برنامههای دیگر عملکرد موردانتظار را نداشته باشند. بهخاطر داشته باشید که نمیتوانید این برنامه را حذف کنید، چون از برنامههای ازپیش نصبشده روی دستگاه است. این برنامه، با غیرفعال کردن، خاموش میشود و در دستگاه پنهان میشود."</string> <string name="app_permission_manager" msgid="3903811137630909550">"مدیر اجازهها"</string> - <string name="never_ask_again" msgid="4728762438198560329">"دوباره سؤال نشود"</string> + <string name="never_ask_again" msgid="4728762438198560329">"دوباره پرسیده نشود"</string> <string name="no_permissions" msgid="3881676756371148563">"مجوزی موجود نیست"</string> <string name="additional_permissions" msgid="5801285469338873430">"اجازههای جانبی"</string> <string name="app_permissions_info_button_label" msgid="7633312050729974623">"باز کردن اطلاعات برنامه"</string> @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"دسترسی <xliff:g id="PERM">%1$s</xliff:g> از این برنامه در <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"نمایش میزان استفاده «دستیار» از میکروفون"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"تنظیمات برنامههای استفادهنشده"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"اگر از برنامه استفاده نمیشود، اجازهها برداشته شوند"</string> diff --git a/PermissionController/res/values-fi/strings.xml b/PermissionController/res/values-fi/strings.xml index 1bb6fbc9f..b1c827b58 100644 --- a/PermissionController/res/values-fi/strings.xml +++ b/PermissionController/res/values-fi/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Näytä Assistantin mikrofonin käyttö"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Käyttämättömien sovellusten asetukset"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Poista luvat, jos sovellusta ei käytetä"</string> diff --git a/PermissionController/res/values-fr-rCA/strings.xml b/PermissionController/res/values-fr-rCA/strings.xml index e4fa8b767..d48c8da8c 100644 --- a/PermissionController/res/values-fr-rCA/strings.xml +++ b/PermissionController/res/values-fr-rCA/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Accès <xliff:g id="PERM">%1$s</xliff:g> pour cette appli sur <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Afficher toutes les autorisations pour <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Afficher toutes les applis qui possèdent cette autorisation"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Afficher l\'usage du microphone de l\'assistant"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Paramètres des applis inutilisées"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Retirer les autorisations si l\'appli est inutilisée"</string> diff --git a/PermissionController/res/values-fr/strings.xml b/PermissionController/res/values-fr/strings.xml index f404da7c6..b0e7e27de 100644 --- a/PermissionController/res/values-fr/strings.xml +++ b/PermissionController/res/values-fr/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Accès à <xliff:g id="PERM">%1$s</xliff:g> pour cette application sur <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Voir toutes les autorisations pour <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Voir toutes les applis ayant cette autorisation"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Afficher l\'utilisation du micro par l\'Assistant"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Paramètres des applis inutilisées"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Supprimer les autorisations si l\'application n\'est pas utilisée"</string> diff --git a/PermissionController/res/values-gl/strings.xml b/PermissionController/res/values-gl/strings.xml index 911eacaf9..2c2f159c4 100644 --- a/PermissionController/res/values-gl/strings.xml +++ b/PermissionController/res/values-gl/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Esta aplicación ten o seguinte permiso de acceso en <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">"Ver todos os permisos de <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas as aplicacións que teñen este permiso"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso do micrófono do Asistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Configuración das aplicacións sen uso"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Quitar permisos se non se usa a aplicación"</string> diff --git a/PermissionController/res/values-gu/strings.xml b/PermissionController/res/values-gu/strings.xml index 977d79579..53a0d39f7 100644 --- a/PermissionController/res/values-gu/strings.xml +++ b/PermissionController/res/values-gu/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"આસિસ્ટંટ દ્વારા વપરાયેલો માઇક્રોફોનની પરવાનગીનો ડેટા બતાવો"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ન વપરાયેલી ઍપના સેટિંગ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ઍપ ઉપયોગમાં ન હોવા પર પરવાનગીઓ કાઢી નાખો"</string> diff --git a/PermissionController/res/values-hi/strings.xml b/PermissionController/res/values-hi/strings.xml index e88e270fe..55fec2550 100644 --- a/PermissionController/res/values-hi/strings.xml +++ b/PermissionController/res/values-hi/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"असिस्टेंट माइक्रोफ़ोन के इस्तेमाल से जुड़ा डेटा दिखाएं"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"इस्तेमाल न हो रहे ऐप के लिए सेटिंग"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ऐप्लिकेशन का इस्तेमाल न होने पर अनुमतियां हटाएं"</string> diff --git a/PermissionController/res/values-hr/strings.xml b/PermissionController/res/values-hr/strings.xml index f35de43ea..ca2a0c4c8 100644 --- a/PermissionController/res/values-hr/strings.xml +++ b/PermissionController/res/values-hr/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Prikaz korištenja mikrofona Asistenta"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Postavke nekorištenih aplikacija"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ukloni dopuštenja ako se aplikacija ne upotrebljava"</string> diff --git a/PermissionController/res/values-hu/strings.xml b/PermissionController/res/values-hu/strings.xml index a0faf34fe..52467905e 100644 --- a/PermissionController/res/values-hu/strings.xml +++ b/PermissionController/res/values-hu/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> – hozzáférés az alkalmazás számára a(z) <xliff:g id="DEVICE_NAME">%2$s</xliff:g> eszközön"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"A(z) <xliff:g id="APP">%1$s</xliff:g> összes engedélyének megtekintése"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Az ezzel az engedéllyel rendelkező összes alkalmazás megtekintése"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mikrofon Segéd általi használatának megjelenítése"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nem használt alkalmazások beállításai"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Engedélyek eltávolítása, ha nem használja az alkalmazást"</string> diff --git a/PermissionController/res/values-hy-v33/strings.xml b/PermissionController/res/values-hy-v33/strings.xml index 99b0b890f..790addb16 100644 --- a/PermissionController/res/values-hy-v33/strings.xml +++ b/PermissionController/res/values-hy-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Այլ ծանուցումներ"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Անտեսված ծանուցումներ"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Ծավալել և տեսնել ևս մեկ զգուշացում}one{Ծավալել և տեսնել ևս # զգուշացում}other{Ծավալել և տեսնել ևս # զգուշացում}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Ծալել"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Ծանուցում։ <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Գործողությունն ավարտված է"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Ծանոթացեք կարգավորումներին, որոնց օգնությամբ կարող եք բարձրացնել ձեր սարքի անվտանգության մակարդակը"</string> diff --git a/PermissionController/res/values-hy/strings.xml b/PermissionController/res/values-hy/strings.xml index 495bd9b38..ac6aa8fe0 100644 --- a/PermissionController/res/values-hy/strings.xml +++ b/PermissionController/res/values-hy/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g>ն օգտագործելու թույլտվություն այս հավելվածի համար <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Ցույց տալ օգնականի կողմից խոսափողի օգտագործման վիճակագրությունը"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Չօգտագործվող հավելվածների կարգավորումներ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Հեռացնել թույլտվությունները, եթե հավելվածը չի օգտագործվում"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"Սահմանափակումներով կարգավորում"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"Անվտանգության նկատառումներից ելնելով՝ այս կարգավորումը ներկայումս անհասանելի է։"</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"Գործողությունը հասանելի չէ հեռախոսազանգի ժամանակ"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n Խաբեբաները սովորաբար ցանկանում են այս տեսակի գործողություններն անել հեռախոսային զրույցների ժամանակ, ուստի դա արգելափակված է՝ ձեր անվտանգության նկատառումներից ելնելով։ Եթե որևէ անծանոթ մարդ ձեզանից խնդրել է նմանատիպ թույլտվություն, ամենայն հավանականությամբ դա խարդախություն է։"</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"Հեռախոսազանգի ժամանակ չի թույլատրվում թույլատրել հավելվածներին տեղադրել այլ հավելվածներ։"</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"Հեռախոսազանգի ժամանակ չի թույլատրվում հատուկ գործառույթները հասանելի դարձնել որևէ հավելվածի։"</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"Հեռախոսազանգի ժամանակ չի թույլատրվում միացնել այս կարգավորումը։"</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"Հավելվածին մերժվել է <xliff:g id="PERMISSION_NAME">%1$s</xliff:g>ի օգտագործման թույլտվությունը"</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"Հավելվածը հայցել է կոնֆիդենցիալ տեղեկությունների օգտագործման թույլտվություն, որը կարող է վտանգի ենթարկել ձեր անձնական և ֆինանսական տեղեկությունները։<xliff:g id="ID_1"><br><br></xliff:g>Հնարավոր է, որ առանց այս սահմանափակված թույլտվության՝ հավելվածը չաշխատի պատշաճ կերպով։ <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>Ինչպես տրամադրել տվյալների օգտագործման թույլտվություն</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"Հավելվածին մերժվել է «<xliff:g id="ROLE_NAME">%1$s</xliff:g>» կատեգորիայում կանխադրված լինելու թույլտվությունը"</string> diff --git a/PermissionController/res/values-in/strings.xml b/PermissionController/res/values-in/strings.xml index d4ce7c291..33cbc2103 100644 --- a/PermissionController/res/values-in/strings.xml +++ b/PermissionController/res/values-in/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Akses <xliff:g id="PERM">%1$s</xliff:g> untuk aplikasi ini di <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Lihat semua izin <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Lihat semua aplikasi yang memiliki izin ini"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Tampilkan penggunaan mikrofon Asisten"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Setelan aplikasi yang tidak digunakan"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Hapus izin jika aplikasi tidak digunakan"</string> diff --git a/PermissionController/res/values-is/strings.xml b/PermissionController/res/values-is/strings.xml index 785da40f2..b997d55d8 100644 --- a/PermissionController/res/values-is/strings.xml +++ b/PermissionController/res/values-is/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Aðgangur að <xliff:g id="PERM">%1$s</xliff:g> fyrir þetta forrit í <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Sjá allar heimildir fyrir „<xliff:g id="APP">%1$s</xliff:g>“"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Sjá öll forrit með þessa heimild"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Sýna hljóðnemanotkun hjálpara"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ónotaðar forritastillingar"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Fjarlægja heimildir ef forrit er ekki notað"</string> diff --git a/PermissionController/res/values-it/strings.xml b/PermissionController/res/values-it/strings.xml index 49fec0ed3..8b5909516 100644 --- a/PermissionController/res/values-it/strings.xml +++ b/PermissionController/res/values-it/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> accesso per questa app su <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Mostra tutte le autorizzazioni di <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostra tutte le app con questa autorizzazione"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostra utilizzo microfono dell\'assistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Impostazioni app inutilizzate"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Rimuovi autorizzazioni se non in uso"</string> diff --git a/PermissionController/res/values-iw/strings.xml b/PermissionController/res/values-iw/strings.xml index ee980429d..4e0b9ec0d 100644 --- a/PermissionController/res/values-iw/strings.xml +++ b/PermissionController/res/values-iw/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"גישה ל<xliff:g id="PERM">%1$s</xliff:g> לאפליקציה הזו ב<xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"השימוש במיקרופון של Assistant"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"הגדרות של אפליקציות שמזמן לא השתמשת בהן"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"הסרת ההרשאות כשלא בשימוש"</string> diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml index 497676f4d..ded17d3f8 100644 --- a/PermissionController/res/values-ja/strings.xml +++ b/PermissionController/res/values-ja/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"アシスタントのマイクの使用を表示"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"使用していないアプリの設定"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"アプリが使用されていない場合に権限を削除"</string> diff --git a/PermissionController/res/values-ka/strings.xml b/PermissionController/res/values-ka/strings.xml index 3e8311d30..45d76168e 100644 --- a/PermissionController/res/values-ka/strings.xml +++ b/PermissionController/res/values-ka/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"(<xliff:g id="PERM">%1$s</xliff:g>) წვდომა ამ აპისთვის <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"ასისტენტის მიკროფონის გამოყენების ჩვენება"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"გამოუყენებელი აპის პარამეტრები"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ნებართვების ამოშლა აპის გამოუყენებლობის შემთხვევაში."</string> diff --git a/PermissionController/res/values-kk/strings.xml b/PermissionController/res/values-kk/strings.xml index e36145d06..1f3bff9e9 100644 --- a/PermissionController/res/values-kk/strings.xml +++ b/PermissionController/res/values-kk/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant микрофонының пайдаланылуын көрсету"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Пайдаланылмайтын қолданба параметрлері"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Қолданба пайдаланылмаса, рұқсаттарды өшіру"</string> diff --git a/PermissionController/res/values-km/strings.xml b/PermissionController/res/values-km/strings.xml index cdf68d190..f5269b85b 100644 --- a/PermissionController/res/values-km/strings.xml +++ b/PermissionController/res/values-km/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"សិទ្ធិចូលប្រើ <xliff:g id="PERM">%1$s</xliff:g> សម្រាប់កម្មវិធីនេះនៅលើ <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"បង្ហាញការប្រើប្រាស់មីក្រូហ្វូនរបស់ជំនួយការ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ការកំណត់កម្មវិធីដែលមិនប្រើ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ដកការអនុញ្ញាតចេញ ប្រសិនបើមិនប្រើប្រាស់កម្មវិធី"</string> diff --git a/PermissionController/res/values-kn/strings.xml b/PermissionController/res/values-kn/strings.xml index 579f810c1..a73c16f47 100644 --- a/PermissionController/res/values-kn/strings.xml +++ b/PermissionController/res/values-kn/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"ಅಸಿಸ್ಟೆಂಟ್ನ ಮೈಕ್ರೋಫೋನ್ ಬಳಕೆಯನ್ನು ತೋರಿಸಿ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ಬಳಕೆಯಾಗದಿರುವ ಆ್ಯಪ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ಆ್ಯಪ್ ಬಳಸದಿದ್ದರೆ ಅನುಮತಿಗಳನ್ನು ತೆಗೆದುಹಾಕಿ"</string> diff --git a/PermissionController/res/values-ko/strings.xml b/PermissionController/res/values-ko/strings.xml index 21157a47b..0206df4cb 100644 --- a/PermissionController/res/values-ko/strings.xml +++ b/PermissionController/res/values-ko/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"어시스턴트 마이크 사용 표시"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"사용하지 않는 앱 설정"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"앱이 사용되지 않는 경우 권한 삭제"</string> diff --git a/PermissionController/res/values-ky/strings.xml b/PermissionController/res/values-ky/strings.xml index eb12e7aef..0de820408 100644 --- a/PermissionController/res/values-ky/strings.xml +++ b/PermissionController/res/values-ky/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Кошумча микрофондун иштешин көрсөтүү"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Колдонулбаган колдонмолордун параметрлери"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Эгер колдонмо пайдаланылбаса, уруксаттар өчүрүлсүн"</string> diff --git a/PermissionController/res/values-lo/strings.xml b/PermissionController/res/values-lo/strings.xml index e82581d20..e4f104116 100644 --- a/PermissionController/res/values-lo/strings.xml +++ b/PermissionController/res/values-lo/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> ເຂົ້າເຖິງແອັບນີ້ຢູ່ <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"ສະແດງການໃຊ້ໄມໂຄຣໂຟນຂອງຜູ້ຊ່ວຍ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ການຕັ້ງຄ່າແອັບທີ່ບໍ່ໄດ້ໃຊ້"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ລຶບສິດອະນຸຍາດຫາກບໍ່ໄດ້ໃຊ້ແອັບ"</string> diff --git a/PermissionController/res/values-lt/strings.xml b/PermissionController/res/values-lt/strings.xml index f2891bf01..1dad58494 100644 --- a/PermissionController/res/values-lt/strings.xml +++ b/PermissionController/res/values-lt/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g> prieiga šiai programai „<xliff:g id="DEVICE_NAME">%2$s</xliff:g>“"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Žr. visus „<xliff:g id="APP">%1$s</xliff:g>“ leidimus"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Žr. visas programas, kurioms suteiktas šis leidimas"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Rodyti Padėjėjo mikrofono naudojimą"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nenaudojamos programos nustatymai"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Pašalinti leidimus, jei programa nenaudojama"</string> diff --git a/PermissionController/res/values-lv/strings.xml b/PermissionController/res/values-lv/strings.xml index 06ebde19f..cec314759 100644 --- a/PermissionController/res/values-lv/strings.xml +++ b/PermissionController/res/values-lv/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Šai lietotnei ir piešķirta piekļuves atļauja “<xliff:g id="PERM">%1$s</xliff:g>” šajā ierīcē: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Skatīt visas lietotnei <xliff:g id="APP">%1$s</xliff:g> piešķirtās atļaujas"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Skatīt visas lietotnes, kam ir šī atļauja"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Rādīt Asistenta mikrofona lietojumu"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Neizmantoto lietotņu iestatījumi"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Noņemt atļaujas, ja lietotne netiek izmantota"</string> diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml index 59a3949b4..eae530379 100644 --- a/PermissionController/res/values-mk/strings.xml +++ b/PermissionController/res/values-mk/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Пристап до <xliff:g id="PERM">%1$s</xliff:g> за апликацијава на <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Прикажи го користењето на микрофонот на „Помошникот“"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Поставки за некористени апликации"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Отстрани ги дозволите ако апликацијата не се користи"</string> diff --git a/PermissionController/res/values-ml/strings.xml b/PermissionController/res/values-ml/strings.xml index 39bfbf8ea..d8a2f29b2 100644 --- a/PermissionController/res/values-ml/strings.xml +++ b/PermissionController/res/values-ml/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"സഹായ മൈക്രോഫോൺ ഉപയോഗം കാണിക്കുക"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ഉപയോഗിക്കാത്ത ആപ്പ് ക്രമീകരണം"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ഉപയോഗിക്കാത്ത ആപ്പാണെങ്കിൽ അനുമതികൾ നീക്കം ചെയ്യുക"</string> diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml index 8904d9a44..fc08b4b3a 100644 --- a/PermissionController/res/values-mn/strings.xml +++ b/PermissionController/res/values-mn/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Туслах микрофон ашиглалтыг харуулах"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ашиглаагүй аппын тохиргоо"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Аппыг ашигладаггүй бол зөвшөөрлийг нь хасах"</string> diff --git a/PermissionController/res/values-mr/strings.xml b/PermissionController/res/values-mr/strings.xml index 983078ba8..688f31707 100644 --- a/PermissionController/res/values-mr/strings.xml +++ b/PermissionController/res/values-mr/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ने मायक्रोफोनचा केलेला वापर दाखवा"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"न वापरलेली ॲप सेटिंग्ज"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"अॅप वापरले नसल्यास, परवानग्या काढून टाका"</string> diff --git a/PermissionController/res/values-ms/strings.xml b/PermissionController/res/values-ms/strings.xml index e08a44e24..2cd37caa0 100644 --- a/PermissionController/res/values-ms/strings.xml +++ b/PermissionController/res/values-ms/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"akses <xliff:g id="PERM">%1$s</xliff:g> untuk apl ini pada <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Lihat semua kebenaran <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Lihat semua apl dengan kebenaran ini"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Tunjukkan penggunaan mikrofon pembantu"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Tetapan apl yang tidak digunakan"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Alih keluar kebenaran jika apl tidak digunakan"</string> diff --git a/PermissionController/res/values-my-v33/strings.xml b/PermissionController/res/values-my-v33/strings.xml index faafbd0d1..6487f5647 100644 --- a/PermissionController/res/values-my-v33/strings.xml +++ b/PermissionController/res/values-my-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"နောက်ထပ် သတိပေးချက်များ"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"ပယ်ထားသော သတိပေးချက်များ"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{ချဲ့ပြီး သတိပေးချက်နောက်တစ်ခု ကြည့်ရန်}other{ချဲ့ပြီး သတိပေးချက်နောက် # ခု ကြည့်ရန်}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"လျှော့ပြပါ"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"သတိပေးချက်။ <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"လုပ်ဆောင်ချက် ပြီးပြီ"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"သင့်စက်တွင် အကာအကွယ်ထည့်သွင်းနိုင်သည့် ဆက်တင်များကို ကြည့်နိုင်သည်"</string> diff --git a/PermissionController/res/values-my/strings.xml b/PermissionController/res/values-my/strings.xml index f01caa774..85297b795 100644 --- a/PermissionController/res/values-my/strings.xml +++ b/PermissionController/res/values-my/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant မိုက်ကရိုဖုန်း အသုံးပြုမှုကို ပြပါ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"အသုံးမပြုသော အက်ပ်ဆက်တင်များ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"အက်ပ်ကိုအသုံးမပြုလျှင် ခွင့်ပြုချက်များ ဖယ်ရှားရန်"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"ကန့်သတ်ဆက်တင်"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"သင့်လုံခြုံရေးအတွက် ဤဆက်တင်ကို လောလောဆယ် မရနိုင်ပါ။"</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"ဖုန်းခေါ်နေစဉ်အတွင်း လုပ်ဆောင်ချက်များ မရနိုင်ပါ"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n လူလိမ်များသည် ဤကဲ့သို့ လုပ်ဆောင်ချက်ကို ဖုန်းပြောဆိုနေစဉ်အတွင်း တောင်းဆိုလေ့ရှိကြသောကြောင့် သင့်အား ကာကွယ်ပေးရန် ၎င်းကိုပိတ်ထားသည်။ သင်မသိသော ပုဂ္ဂိုလ်တစ်ဦးဦးက ဤလုပ်ဆောင်ချက်ကို ဆောင်ရွက်ရန် သင့်အားပြောဆိုနေပါက လိမ်လည်မှုဖြစ်နိုင်သည်။"</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"ဖုန်းခေါ်ဆိုမှုအတွင်း အခြားအက်ပ်များ ထည့်သွင်းရန် အက်ပ်များအား ခွင့်ပြုခြင်းကို လုပ်ခွင့်မပြုပါ။"</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"ဖုန်းခေါ်ဆိုမှုအတွင်း အက်ပ်တစ်ခုကို အများသုံးနိုင်မှုသုံးခွင့်ပေးခြင်း ခွင့်မပြုပါ။"</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"ဖုန်းခေါ်ဆိုမှုအတွင်း ဤဆက်တင်ဖွင့်ခြင်း ခွင့်မပြုပါ။"</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"အက်ပ်ကို <xliff:g id="PERMISSION_NAME">%1$s</xliff:g> သုံးခွင့် ငြင်းပယ်ထားသည်"</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"အက်ပ်သည် သင်၏ ပုဂ္ဂိုလ်ရေးနှင့် ငွေကြေးဆိုင်ရာ အချက်အလက်များကို အန္တရာယ်ဖြစ်စေနိုင်သော သတိထားရမည့် ခွင့်ပြုချက်သုံးရန် တောင်းဆိုထားသည်။<xliff:g id="ID_1"><br><br></xliff:g>အက်ပ်သည် ဤကန့်သတ်ထားသော ခွင့်ပြုချက်မရှိပါက ကောင်းစွာမလုပ်ဆောင်ခြင်း ဖြစ်နိုင်သည်။ <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>သုံးခွင့်ပြုနည်းကို လေ့လာရန်</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"အက်ပ်အား မူရင်း <xliff:g id="ROLE_NAME">%1$s</xliff:g> အဖြစ် လုပ်ဆောင်ခွင့် ငြင်းပယ်ထားသည်"</string> diff --git a/PermissionController/res/values-nb-v33/strings.xml b/PermissionController/res/values-nb-v33/strings.xml index a5f067d71..9f4910da2 100644 --- a/PermissionController/res/values-nb-v33/strings.xml +++ b/PermissionController/res/values-nb-v33/strings.xml @@ -33,7 +33,7 @@ <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Skjul"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Varsel. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Handlingen er fullført"</string> - <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Sjekk innstillinger som kan øke beskyttelsen til enheten"</string> + <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Sjekk innstillinger som kan gi enheten bedre beskyttelse"</string> <string name="safety_center_qs_page_landing" msgid="1717368301679228128">"Hurtiginnstillinger for sikkerhet og personvern"</string> <string name="safety_center_qs_close_button" msgid="1352313308176244599">"Lukk"</string> <string name="safety_center_qs_expand_action" msgid="2193190557696484169">"Vis alternativer"</string> diff --git a/PermissionController/res/values-nb/strings.xml b/PermissionController/res/values-nb/strings.xml index 2e64a1ae6..61d7e6cce 100644 --- a/PermissionController/res/values-nb/strings.xml +++ b/PermissionController/res/values-nb/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g>-tilgang for denne appen på <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Se alle tillatelsene <xliff:g id="APP">%1$s</xliff:g> har"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Se alle apper med denne tillatelsen"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Vis bruk av assistentmikrofonen"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Innstillinger for ubrukte apper"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Fjern tillatelser hvis appen ikke brukes"</string> diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml index 8f9152c8a..4c5b37c3f 100644 --- a/PermissionController/res/values-ne/strings.xml +++ b/PermissionController/res/values-ne/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"सहायकको माइक्रोफोन प्रयोगसम्बन्धी डेटा देखाउनुहोस्"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"प्रयोग नगरिएको एपसम्बन्धी सेटिङ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"यो एप प्रयोग नहुँदा यसलाई दिइएका अनुमतिहरू रद्द गर्नुहोस्"</string> diff --git a/PermissionController/res/values-nl/strings.xml b/PermissionController/res/values-nl/strings.xml index 9a646f357..55f4c2d44 100644 --- a/PermissionController/res/values-nl/strings.xml +++ b/PermissionController/res/values-nl/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Toegang tot <xliff:g id="PERM">%1$s</xliff:g> voor deze app op <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Alle rechten van <xliff:g id="APP">%1$s</xliff:g> bekijken"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Alle apps met dit recht bekijken"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Gebruik van Assistent-microfoon tonen"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Niet-gebruikte app-instellingen"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Rechten intrekken als app niet wordt gebruikt"</string> diff --git a/PermissionController/res/values-or/strings.xml b/PermissionController/res/values-or/strings.xml index 4703749b8..51b45c726 100644 --- a/PermissionController/res/values-or/strings.xml +++ b/PermissionController/res/values-or/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ମାଇକ୍ରୋଫୋନ୍ ବ୍ୟବହାର ଦେଖାନ୍ତୁ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ଅବ୍ୟବହୃତ ଆପ ସେଟିଂସ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ଯଦି ଆପ୍ ବ୍ୟବହାର କରାଯାଇନାହିଁ, ତେବେ ଅନୁମତିଗୁଡ଼ିକୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string> diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml index b7585b0b0..b5d0dab61 100644 --- a/PermissionController/res/values-pa/strings.xml +++ b/PermissionController/res/values-pa/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistant ਦੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਦਿਖਾਓ"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ਅਣਵਰਤੀ ਐਪ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ਐਪ ਨੂੰ ਨਾ ਵਰਤੇ ਜਾਣ \'ਤੇ ਇਸ ਲਈ ਦਿੱਤੀਆਂ ਇਜਾਜ਼ਤਾਂ ਨੂੰ ਹਟਾ ਦਿਓ"</string> diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml index 966c0fd4e..fe983f17e 100644 --- a/PermissionController/res/values-pl/strings.xml +++ b/PermissionController/res/values-pl/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Aplikacja ma przyznane uprawnienie <xliff:g id="PERM">%1$s</xliff:g> na tym urządzeniu: <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobacz wszystkie uprawnienia aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Wyświetl wszystkie aplikacje z tym uprawnieniem"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Pokaż użycie mikrofonu w Asystencie"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ustawienia nieużywanych aplikacji"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Usuń uprawnienia, jeśli aplikacja jest nieużywana"</string> diff --git a/PermissionController/res/values-pt-rBR/strings.xml b/PermissionController/res/values-pt-rBR/strings.xml index 156ff9162..286140617 100644 --- a/PermissionController/res/values-pt-rBR/strings.xml +++ b/PermissionController/res/values-pt-rBR/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acesso de <xliff:g id="PERM">%1$s</xliff:g> para esse app no <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar todos os apps que têm esta permissão"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string> diff --git a/PermissionController/res/values-pt-rPT/strings.xml b/PermissionController/res/values-pt-rPT/strings.xml index 34aff66b1..edd22cfe0 100644 --- a/PermissionController/res/values-pt-rPT/strings.xml +++ b/PermissionController/res/values-pt-rPT/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acesso a <xliff:g id="PERM">%1$s</xliff:g> para esta app no dispositivo <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as autorizações da app <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ver todas as apps com esta autorização"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar utilização do microfone do assistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Definições de apps não usadas"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remover autorizações se a app não for utilizada"</string> @@ -362,13 +366,13 @@ <string name="role_browser_request_title" msgid="2895200507835937192">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de navegador predefinida?"</string> <string name="role_browser_request_description" msgid="5888803407905985941">"Não são necessárias autorizações."</string> <string name="role_dialer_label" msgid="1100224146343237968">"App de telefone predefinida"</string> - <string name="role_dialer_short_label" msgid="7186888549465352489">"App Telefone"</string> + <string name="role_dialer_short_label" msgid="7186888549465352489">"App de telefone"</string> <string name="role_dialer_description" msgid="8768708633696539612">"Apps que permitem fazer e receber chamadas no seu dispositivo"</string> <string name="role_dialer_request_title" msgid="5959618560705912058">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app de telefone predefinida?"</string> <string name="role_dialer_request_description" msgid="6288839625724909320">"Esta app fica com acesso à sua Câmara, Contactos, Microfone, Telefone e SMS"</string> <string name="role_dialer_search_keywords" msgid="3324448983559188087">"telefone"</string> <string name="role_sms_label" msgid="8456999857547686640">"App de SMS predefinida"</string> - <string name="role_sms_short_label" msgid="4371444488034692243">"app de SMS"</string> + <string name="role_sms_short_label" msgid="4371444488034692243">"App de SMS"</string> <string name="role_sms_description" msgid="3424020199148153513">"Apps que permitem usar o seu número de telefone para enviar e receber mensagens de texto, fotos, vídeos e muito mais."</string> <string name="role_sms_request_title" msgid="7953552109601185602">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como app SMS predefinida?"</string> <string name="role_sms_request_description" msgid="2691004766132144886">"Esta app fica com acesso à sua Câmara, Contactos, Ficheiros e multimédia, Microfone, Telefone e SMS"</string> @@ -380,7 +384,7 @@ <string name="role_emergency_request_description" msgid="131645948770262850">"Não são necessárias autorizações."</string> <string name="role_emergency_search_keywords" msgid="1920007722599213358">"em caso de emergência"</string> <string name="role_home_label" msgid="3871847846649769412">"App página inicial predefinida"</string> - <string name="role_home_short_label" msgid="8544733747952272337">"App Página inicial"</string> + <string name="role_home_short_label" msgid="8544733747952272337">"App de página inicial"</string> <string name="role_home_description" msgid="7997371519626556675">"Também conhecidas por \"launcher\" são apps que substituem os ecrãs principais no Android e dão acesso aos conteúdos e às funcionalidades do seu dispositivo"</string> <string name="role_home_request_title" msgid="738136983453341081">"Quer definir o <xliff:g id="APP_NAME">%1$s</xliff:g> como a app Página inicial predefinida?"</string> <string name="role_home_request_description" msgid="2658833966716057673">"Não são necessárias autorizações."</string> diff --git a/PermissionController/res/values-pt/strings.xml b/PermissionController/res/values-pt/strings.xml index 156ff9162..286140617 100644 --- a/PermissionController/res/values-pt/strings.xml +++ b/PermissionController/res/values-pt/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acesso de <xliff:g id="PERM">%1$s</xliff:g> para esse app no <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ver todas as permissões do app <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Mostrar todos os apps que têm esta permissão"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Mostrar uso de microfone pelo Assistente"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Configurações de apps não usados"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Remover permissões se o app não for usado"</string> diff --git a/PermissionController/res/values-ro/strings.xml b/PermissionController/res/values-ro/strings.xml index 6a0325811..76cd84d73 100644 --- a/PermissionController/res/values-ro/strings.xml +++ b/PermissionController/res/values-ro/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Acces de <xliff:g id="PERM">%1$s</xliff:g> pentru această aplicație pe <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Vezi toate permisiunile aplicației <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Vezi toate aplicațiile cu această permisiune"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Afișează datele de utilizare a microfonului cu Asistentul"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Setările aplicațiilor nefolosite"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Elimină permisiunile dacă aplicația nu este folosită"</string> diff --git a/PermissionController/res/values-ru/strings.xml b/PermissionController/res/values-ru/strings.xml index 2fe75db49..f4058b0f4 100644 --- a/PermissionController/res/values-ru/strings.xml +++ b/PermissionController/res/values-ru/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Разрешение \"<xliff:g id="PERM">%1$s</xliff:g>\" для этого приложения на устройстве \"<xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Показывать сведения об использовании микрофона Ассистентом"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Настройки неиспользуемых приложений"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Отзывать разрешения, если приложение не используется"</string> diff --git a/PermissionController/res/values-si/strings.xml b/PermissionController/res/values-si/strings.xml index 7fcc23787..e158d0e27 100644 --- a/PermissionController/res/values-si/strings.xml +++ b/PermissionController/res/values-si/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"සහායක මයික්රෆෝන භාවිතය පෙන්වන්න"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"භාවිත නොකළ යෙදුම් සැකසීම්"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"යෙදුම භාවිත කර නැති නම් අවසර ඉවත් කරන්න"</string> diff --git a/PermissionController/res/values-sk-watch/strings.xml b/PermissionController/res/values-sk-watch/strings.xml index 1a7e89701..52503904f 100644 --- a/PermissionController/res/values-sk-watch/strings.xml +++ b/PermissionController/res/values-sk-watch/strings.xml @@ -23,10 +23,10 @@ <string name="generic_yes" msgid="2489207724988649846">"Áno"</string> <string name="generic_cancel" msgid="2631708607129269698">"Zrušiť"</string> <string name="permission_access_always" msgid="2107115233573823032">"Po celý čas"</string> - <string name="permission_access_only_foreground" msgid="4412115020089923986">"Pri používaní"</string> + <string name="permission_access_only_foreground" msgid="4412115020089923986">"Pri používaní aplikácie"</string> <string name="app_permission_button_allow_always" msgid="4920899432212307102">"Po celý čas"</string> - <string name="app_permission_button_allow_foreground" msgid="7186980598244864830">"Pri používaní"</string> + <string name="app_permission_button_allow_foreground" msgid="7186980598244864830">"Pri používaní aplikácie"</string> <string name="grant_dialog_button_allow_always" msgid="7130695257254694576">"Po celý čas"</string> - <string name="grant_dialog_button_allow_foreground" msgid="8917595344037255090">"Pri používaní"</string> + <string name="grant_dialog_button_allow_foreground" msgid="8917595344037255090">"Pri používaní aplikácie"</string> <string name="grant_dialog_button_allow_background" msgid="6104993390936535493">"Po celý čas"</string> </resources> diff --git a/PermissionController/res/values-sk/strings.xml b/PermissionController/res/values-sk/strings.xml index a1680e4d7..92a77873f 100644 --- a/PermissionController/res/values-sk/strings.xml +++ b/PermissionController/res/values-sk/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Prístup k položke <xliff:g id="PERM">%1$s</xliff:g> pre túto aplikáciu v zariadení <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Zobraziť všetky povolenia aplikácie <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Zobraziť všetky aplikácie s týmto povolením"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Zobraziť používanie mikrofónu Asistentom"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavenia nepoužívaných aplikácií"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Odstrániť povolenia, ak sa aplikácia nepoužíva"</string> diff --git a/PermissionController/res/values-sl/strings.xml b/PermissionController/res/values-sl/strings.xml index 92e698b0e..3a9b71fa0 100644 --- a/PermissionController/res/values-sl/strings.xml +++ b/PermissionController/res/values-sl/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Dostop do dovoljenja »<xliff:g id="PERM">%1$s</xliff:g>« za to aplikacijo v napravi <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Ogled vseh dovoljenj za aplikacijo <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Ogled vseh aplikacij s tem dovoljenjem"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Prikaz uporabe pomožnega mikrofona"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Nastavitve neuporabljenih aplikacij"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Odstrani dovoljenja, če aplikacija ni v uporabi"</string> diff --git a/PermissionController/res/values-sq/strings.xml b/PermissionController/res/values-sq/strings.xml index 33c1f8066..74d19dca0 100644 --- a/PermissionController/res/values-sq/strings.xml +++ b/PermissionController/res/values-sq/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Qasja te <xliff:g id="PERM">%1$s</xliff:g> për këtë aplikacion në <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Shiko të gjitha lejet e aplikacionit \"<xliff:g id="APP">%1$s</xliff:g>\""</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Shiko të gjitha aplikacionet me këtë leje"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Shfaq përdorimin e mikrofonit të \"Asistentit\""</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Cilësimet e aplikacioneve të papërdorura"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Hiq lejet nëse aplikacioni nuk është përdorur"</string> diff --git a/PermissionController/res/values-sr/strings.xml b/PermissionController/res/values-sr/strings.xml index 925baa7bb..19815a0d4 100644 --- a/PermissionController/res/values-sr/strings.xml +++ b/PermissionController/res/values-sr/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Ова апликација има приступ за: <xliff:g id="PERM">%1$s</xliff:g> на уређају <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Прикажи како Помоћник користи микрофон"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Подешавања некоришћених апликација"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Уклони дозволе ако се апликација не користи"</string> diff --git a/PermissionController/res/values-sv/strings.xml b/PermissionController/res/values-sv/strings.xml index bd57656e8..710c8692d 100644 --- a/PermissionController/res/values-sv/strings.xml +++ b/PermissionController/res/values-sv/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Åtkomst till <xliff:g id="PERM">%1$s</xliff:g> för den här appen på <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Visa alla behörigheter för <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Visa alla appar med den här behörigheten"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Visa mikrofonanvändning för assistenten"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Inställningar för appar som inte används"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ta bort behörigheter om en app inte används"</string> diff --git a/PermissionController/res/values-sw/strings.xml b/PermissionController/res/values-sw/strings.xml index 918a4c864..8eef23afa 100644 --- a/PermissionController/res/values-sw/strings.xml +++ b/PermissionController/res/values-sw/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Ufikaiji wa <xliff:g id="PERM">%1$s</xliff:g> katika programu hii kwenye <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Angalia ruhusa zote za <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Angalia programu zote zenye ruhusa hii"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Onyesha matumizi ya maikrofoni ya mratibu"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Mipangilio ya programu zisizotumika"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ondoa ruhusa ikiwa programu haitumiki"</string> diff --git a/PermissionController/res/values-ta/strings.xml b/PermissionController/res/values-ta/strings.xml index 61ec88213..c218cde22 100644 --- a/PermissionController/res/values-ta/strings.xml +++ b/PermissionController/res/values-ta/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"அசிஸ்டண்ட் மைக்ரோஃபோன் உபயோகத்தைக் காட்டு"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"பயன்படுத்தப்படாத ஆப்ஸ் அமைப்புகள்"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"இந்த ஆப்ஸ் பயன்படுத்தப்படவில்லை என்றால் அனுமதிகளை அகற்றவும்"</string> diff --git a/PermissionController/res/values-te/strings.xml b/PermissionController/res/values-te/strings.xml index d1b689674..eb871fafa 100644 --- a/PermissionController/res/values-te/strings.xml +++ b/PermissionController/res/values-te/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"అసిస్టెంట్ మైక్రోఫోన్ వినియోగాన్ని చూపు"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"ఉపయోగించని యాప్ సెట్టింగ్లు"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"యాప్ని ఉపయోగించకపోతే, అనుమతులను తీసివేయండి"</string> diff --git a/PermissionController/res/values-th/strings.xml b/PermissionController/res/values-th/strings.xml index d7db6cf53..d5b507a73 100644 --- a/PermissionController/res/values-th/strings.xml +++ b/PermissionController/res/values-th/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"สิทธิ์เข้าถึง<xliff:g id="PERM">%1$s</xliff:g>สำหรับแอปนี้บน <xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"แสดงการใช้ไมโครโฟนของ Assistant"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"การตั้งค่าแอปที่ไม่ได้ใช้"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"นำสิทธิ์ออกหากไม่ได้ใช้งานแอป"</string> diff --git a/PermissionController/res/values-tl/strings.xml b/PermissionController/res/values-tl/strings.xml index e5526ddc8..85c4f0460 100644 --- a/PermissionController/res/values-tl/strings.xml +++ b/PermissionController/res/values-tl/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"access sa <xliff:g id="PERM">%1$s</xliff:g> para sa app na ito sa <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Tingnan ang lahat ng pahintulot ng <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Tingnan ang lahat ng app na may ganitong pahintulot"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Ipakita ang paggamit ng mikropono ng assistant"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Mga setting ng hindi ginagamit na app"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Alisin ang mga pahintulot kung hindi ginagamit ang app"</string> diff --git a/PermissionController/res/values-tr-v33/strings.xml b/PermissionController/res/values-tr-v33/strings.xml index 9bab1071a..ee3827f93 100644 --- a/PermissionController/res/values-tr-v33/strings.xml +++ b/PermissionController/res/values-tr-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Diğer uyarılar"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Reddedilen uyarılar"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Genişletip bir uyarıyı daha görün}other{Genişletip # uyarıyı daha görün}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Daralt"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Uyarı. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"İşlem tamamlandı"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Cihazınızın korumasını artırabilecek ayarlara göz atın"</string> diff --git a/PermissionController/res/values-tr/strings.xml b/PermissionController/res/values-tr/strings.xml index 41598409e..2742a17d6 100644 --- a/PermissionController/res/values-tr/strings.xml +++ b/PermissionController/res/values-tr/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g> adlı cihazda bu uygulamanın <xliff:g id="PERM">%1$s</xliff:g> erişimi"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Tüm <xliff:g id="APP">%1$s</xliff:g> izinlerini göster"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu izne sahip tüm uygulamaları göster"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Yardımcı mikrofon kullanımını göster"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Kullanılmayan uygulama ayarları"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Uygulama kullanılmıyorsa izinleri kaldır"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"Kısıtlanmış ayar"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"Güvenliğiniz için bu ayar şu anda kullanılamıyor."</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"İşlem, telefon görüşmesi sırasında yapılamaz"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n Dolandırıcıların genellikle telefon görüşmesi sırasında talep ettiği bu tür işlemler sizi korumak için engellenir. Tanımadığınız biri tarafından bu işlemi yapmanız isteniyorsa dolandırılıyor olabilirsiniz."</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"Telefon görüşmesi sırasında uygulamaların başka uygulama yüklemesine izin verilmez."</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"Telefon görüşmesi sırasında bir uygulamaya erişilebilirlik izni verilemez."</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"Telefon görüşmesi sırasında bu ayarın etkinleştirilmesine izin verilmez."</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"Uygulamanın <xliff:g id="PERMISSION_NAME">%1$s</xliff:g> iznine erişimi reddedildi"</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"Uygulama, kişisel ve finansal bilgilerinizi riske atabilecek hassas bir izne erişim istedi.<xliff:g id="ID_1"><br><br></xliff:g>Bu kısıtlı izin olmadan uygulama düzgün çalışmayabilir. <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>Erişime nasıl izin vereceğinizi öğrenin</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"Uygulamanın varsayılan <xliff:g id="ROLE_NAME">%1$s</xliff:g> olarak kullanılma erişimi reddedildi"</string> diff --git a/PermissionController/res/values-uk-v33/strings.xml b/PermissionController/res/values-uk-v33/strings.xml index 1368408ff..24571a6d7 100644 --- a/PermissionController/res/values-uk-v33/strings.xml +++ b/PermissionController/res/values-uk-v33/strings.xml @@ -30,8 +30,7 @@ <string name="safety_center_more_issues_card_title" msgid="7425844746197493312">"Більше сповіщень"</string> <string name="safety_center_dismissed_issues_card_title" msgid="2340129842725145733">"Закриті сповіщення"</string> <string name="safety_center_more_issues_card_expand_action" msgid="7109451851052272946">"{count,plural, =1{Розгорніть і перегляньте ще одне сповіщення}one{Розгорніть і перегляньте ще # сповіщення}few{Розгорніть і перегляньте ще # сповіщення}many{Розгорніть і перегляньте ще # сповіщень}other{Розгорніть і перегляньте ще # сповіщення}}"</string> - <!-- no translation found for safety_center_more_issues_card_collapse_action (7485597582198474637) --> - <skip /> + <string name="safety_center_more_issues_card_collapse_action" msgid="7485597582198474637">"Згорнути"</string> <string name="safety_center_issue_card_prefix_content_description" msgid="1447445289637043544">"Сповіщення. <xliff:g id="ISSUE_CARD_TITLE">%1$s</xliff:g>"</string> <string name="safety_center_resolved_issue_fallback" msgid="8548932070610766651">"Дію виконано"</string> <string name="safety_center_qs_status_summary" msgid="5193925895830451177">"Перевірте налаштування, які можуть посилити захист вашого пристрою"</string> diff --git a/PermissionController/res/values-uk/strings.xml b/PermissionController/res/values-uk/strings.xml index 55ba545e2..b3b8c444f 100644 --- a/PermissionController/res/values-uk/strings.xml +++ b/PermissionController/res/values-uk/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="PERM">%1$s</xliff:g>: доступ для цього додатка (<xliff:g id="DEVICE_NAME">%2$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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Показати статус мікрофона Асистента"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Налаштування невикористовуваних додатків"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Відкликати дозволи, якщо додаток не використовується"</string> @@ -675,14 +679,10 @@ <string name="enhanced_confirmation_dialog_title" msgid="7562437438040966351">"Налаштування з обмеженнями"</string> <string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"З міркувань безпеки це налаштування наразі недоступне."</string> <string name="enhanced_confirmation_phone_state_dialog_title" msgid="5230100829862738467">"Дія недоступна під час телефонного виклику"</string> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_desc (8861786545031902839) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_install_desc_prefix (2832355924914011814) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_a11y_desc_prefix (5336417371950046729) --> - <skip /> - <!-- no translation found for enhanced_confirmation_phone_state_dialog_generic_desc_prefix (4453183594330342865) --> - <skip /> + <string name="enhanced_confirmation_phone_state_dialog_desc" msgid="8861786545031902839">"<xliff:g id="SETTING_DESCRIPTION">%1$s</xliff:g>\n\n Шахраї часто просять виконати такі дії під час телефонних розмов, тому цю можливість заблоковано задля вашого захисту. Якщо незнайома особа просить вас виконати таку дію, це може бути шахрайством."</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix" msgid="2832355924914011814">"Під час телефонного виклику не можна надавати додаткам дозвіл на встановлення інших додатків."</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix" msgid="5336417371950046729">"Під час телефонного виклику додатку не можна надавати доступ до функцій доступності."</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix" msgid="4453183594330342865">"Під час телефонного виклику не можна вмикати це налаштування."</string> <string name="enhanced_confirmation_dialog_title_permission" msgid="2149144789394238266">"Додатку не надано дозвіл \"<xliff:g id="PERMISSION_NAME">%1$s</xliff:g>\""</string> <string name="enhanced_confirmation_dialog_desc_permission" msgid="3150778951946468945">"Додаток запитав дозвіл на доступ до чутливих даних, що може поставити під загрозу вашу особисту й фінансову інформацію.<xliff:g id="ID_1"><br><br></xliff:g>Без цього обмеженого дозволу додаток може не працювати належним чином. <a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>>Як надати доступ</a>"</string> <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"Додатку не надано доступ до ролі \"<xliff:g id="ROLE_NAME">%1$s</xliff:g>\" за умовчанням"</string> diff --git a/PermissionController/res/values-ur/strings.xml b/PermissionController/res/values-ur/strings.xml index 01a32f16b..04a340176 100644 --- a/PermissionController/res/values-ur/strings.xml +++ b/PermissionController/res/values-ur/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"اسسٹنٹ مائیکروفون کا استعمال دکھائیں"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"غیر استعمال شدہ ایپ کی ترتیبات"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"ایپ کے استعمال نہ ہونے پر اجازتیں ہٹائیں"</string> diff --git a/PermissionController/res/values-uz/strings.xml b/PermissionController/res/values-uz/strings.xml index 9d12cb873..8632221f4 100644 --- a/PermissionController/res/values-uz/strings.xml +++ b/PermissionController/res/values-uz/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"<xliff:g id="DEVICE_NAME">%2$s</xliff:g>da bu ilova uchun <xliff:g id="PERM">%1$s</xliff:g> kirish ruxsati"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"<xliff:g id="APP">%1$s</xliff:g> uchun berilgan barcha ruxsatlar"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bu ruxsatga ega barcha ilovalar"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Assistent uchun mikrofondan foydalanishni koʻrsatish"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Ishlatilmagan ilova sozlamalari"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Ishlatilmayotgan ilovalardan ruxsatlarni olib tashlash"</string> diff --git a/PermissionController/res/values-vi/strings.xml b/PermissionController/res/values-vi/strings.xml index b9afdcb56..1ebbc4cf2 100644 --- a/PermissionController/res/values-vi/strings.xml +++ b/PermissionController/res/values-vi/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Quyền truy cập <xliff:g id="PERM">%1$s</xliff:g> cho ứng dụng này trên <xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Xem tất cả các quyền của <xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Xem tất cả ứng dụng có quyền này"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Hiển thị việc sử dụng micrô của Trợ lý"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Chế độ cài đặt cho ứng dụng không dùng đến"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Thu hồi quyền nếu bạn không dùng ứng dụng"</string> diff --git a/PermissionController/res/values-zh-rCN/strings.xml b/PermissionController/res/values-zh-rCN/strings.xml index cc28b5085..3dac8ef31 100644 --- a/PermissionController/res/values-zh-rCN/strings.xml +++ b/PermissionController/res/values-zh-rCN/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"显示 Google 助理麦克风使用情况"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"闲置应用设置"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"如果未使用此应用,则移除相关权限"</string> diff --git a/PermissionController/res/values-zh-rHK/strings.xml b/PermissionController/res/values-zh-rHK/strings.xml index 301fddbe1..9d4ae5129 100644 --- a/PermissionController/res/values-zh-rHK/strings.xml +++ b/PermissionController/res/values-zh-rHK/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"顯示「Google 助理」麥克風使用情況"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"不使用的應用程式設定"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"如不使用應用程式,即移除權限"</string> diff --git a/PermissionController/res/values-zh-rTW/strings.xml b/PermissionController/res/values-zh-rTW/strings.xml index a7aad3d3c..4e5482bdb 100644 --- a/PermissionController/res/values-zh-rTW/strings.xml +++ b/PermissionController/res/values-zh-rTW/strings.xml @@ -202,6 +202,10 @@ <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> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"顯示 Google 助理的麥克風使用狀況"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"未使用的應用程式設定"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"如果應用程式未使用,讓系統移除相關權限"</string> diff --git a/PermissionController/res/values-zu/strings.xml b/PermissionController/res/values-zu/strings.xml index ee9e92985..696946243 100644 --- a/PermissionController/res/values-zu/strings.xml +++ b/PermissionController/res/values-zu/strings.xml @@ -202,6 +202,10 @@ <string name="app_permission_header_with_device_name" msgid="7193042925656173271">"Ukufinyelela kwe-<xliff:g id="PERM">%1$s</xliff:g> kwale app kuvuliwe ku-<xliff:g id="DEVICE_NAME">%2$s</xliff:g>"</string> <string name="app_permission_footer_app_permissions_link" msgid="4926890342636587393">"Bona zonke izimvume ze-<xliff:g id="APP">%1$s</xliff:g>"</string> <string name="app_permission_footer_permission_apps_link" msgid="3941988129992794327">"Bona zonke izinhlelo zokusebenza ngale mvume"</string> + <!-- no translation found for app_permission_info_button (8973692370208562556) --> + <skip /> + <!-- no translation found for app_permission_settings_button (4582916817451973752) --> + <skip /> <string name="assistant_mic_label" msgid="1011432357152323896">"Bonisa ukusetshenziswa kwe-microphone kamsizi"</string> <string name="unused_apps_category_title" msgid="2988455616845243901">"Amasethingi we-app engasetshenziswanga"</string> <string name="auto_revoke_label" msgid="5068393642936571656">"Susa izimvume uma uhlelo lokusebenza lungasetshenziswa"</string> diff --git a/PermissionController/res/values/overlayable.xml b/PermissionController/res/values/overlayable.xml index ea7929746..e94c5bd04 100644 --- a/PermissionController/res/values/overlayable.xml +++ b/PermissionController/res/values/overlayable.xml @@ -461,89 +461,6 @@ <item type="style" name="AppDataSharingUpdateSettingsIcon" /> <!-- END SAFETY LABELS STYLE --> - <!--START WEAR SPECIFIC MATERIAL2 FONT STRINGS --> - <item type="string" name="wear_material_compose_display_1_font_family" /> - <item type="string" name="wear_material_compose_display_2_font_family" /> - <item type="string" name="wear_material_compose_display_3_font_family" /> - <item type="string" name="wear_material_compose_title_1_font_family" /> - <item type="string" name="wear_material_compose_title_2_font_family" /> - <item type="string" name="wear_material_compose_title_3_font_family" /> - <item type="string" name="wear_material_compose_body_1_font_family" /> - <item type="string" name="wear_material_compose_body_2_font_family" /> - <item type="string" name="wear_material_compose_button_font_family" /> - <item type="string" name="wear_material_compose_caption_1_font_family" /> - <item type="string" name="wear_material_compose_caption_2_font_family" /> - <item type="string" name="wear_material_compose_caption_3_font_family" /> - <!--END WEAR SPECIFIC MATERIAL2 FONT STRINGS --> - - <!--START WEAR SPECIFIC MATERIAL3 FONT FACE TOKENS--> - <item type="string" name="wear_compose_material3_arc_small_font_family" /> - <item type="string" name="wear_compose_material3_arc_medium_font_family" /> - <item type="string" name="wear_compose_material3_arc_large_font_family" /> - - <item type="string" name="wear_compose_material3_body_extra_small_font_family" /> - <item type="string" name="wear_compose_material3_body_small_font_family" /> - <item type="string" name="wear_compose_material3_body_medium_font_family" /> - <item type="string" name="wear_compose_material3_body_large_font_family" /> - - <item type="string" name="wear_compose_material3_display_small_font_family" /> - <item type="string" name="wear_compose_material3_display_medium_font_family" /> - <item type="string" name="wear_compose_material3_display_large_font_family" /> - - <item type="string" name="wear_compose_material3_label_small_font_family" /> - <item type="string" name="wear_compose_material3_label_medium_font_family" /> - <item type="string" name="wear_compose_material3_label_large_font_family" /> - - <item type="string" name="wear_compose_material3_numeral_extra_small_font_family" /> - <item type="string" name="wear_compose_material3_numeral_small_font_family" /> - <item type="string" name="wear_compose_material3_numeral_medium_font_family" /> - <item type="string" name="wear_compose_material3_numeral_large_font_family" /> - <item type="string" name="wear_compose_material3_numeral_extra_large_font_family" /> - - <item type="string" name="wear_compose_material3_title_small_font_family" /> - <item type="string" name="wear_compose_material3_title_medium_font_family" /> - <item type="string" name="wear_compose_material3_title_large_font_family" /> - <!--END WEAR SPECIFIC MATERIAL3 FONT FACE TOKENS--> - - - <!--START WEAR SPECIFIC MATERIAL3 FONT SIZE TOKENS--> - <item type="dimen" name="wear_compose_material3_arc_small_font_size" /> - <item type="dimen" name="wear_compose_material3_arc_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_arc_large_font_size" /> - - <item type="dimen" name="wear_compose_material3_body_extra_small_font_size" /> - <item type="dimen" name="wear_compose_material3_body_small_font_size" /> - <item type="dimen" name="wear_compose_material3_body_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_body_large_font_size" /> - - <item type="dimen" name="wear_compose_material3_display_small_font_size" /> - <item type="dimen" name="wear_compose_material3_display_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_display_large_font_size" /> - - <item type="dimen" name="wear_compose_material3_label_small_font_size" /> - <item type="dimen" name="wear_compose_material3_label_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_label_large_font_size" /> - - <item type="dimen" name="wear_compose_material3_numeral_extra_small_font_size" /> - <item type="dimen" name="wear_compose_material3_numeral_small_font_size" /> - <item type="dimen" name="wear_compose_material3_numeral_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_numeral_large_font_size" /> - <item type="dimen" name="wear_compose_material3_numeral_extra_large_font_size" /> - - <item type="dimen" name="wear_compose_material3_title_small_font_size" /> - <item type="dimen" name="wear_compose_material3_title_medium_font_size" /> - <item type="dimen" name="wear_compose_material3_title_large_font_size" /> - <!--END WEAR SPECIFIC MATERIAL3 FONT SIZE TOKENS--> - - <!--START WEAR SPECIFIC MATERIAL3 SHAPE TOKENS--> - <item type="dimen" name="wear_compose_material3_shape_corner_extra_small_size" /> - <item type="dimen" name="wear_compose_material3_shape_corner_small_size" /> - <item type="dimen" name="wear_compose_material3_shape_corner_medium_size" /> - <item type="dimen" name="wear_compose_material3_shape_corner_large_size" /> - <item type="dimen" name="wear_compose_material3_shape_corner_extra_large_size" /> - <!--END WEAR SPECIFIC MATERIAL3 SHAPE TOKENS--> - - <!-- START ENHANCED CONFIRMATION DIALOG --> <item type="style" name="Theme.EnhancedConfirmationDialog" /> <item type="style" name="Theme.EnhancedConfirmationDialogFragment" /> diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml index b28fbcef2..48747bd2a 100644 --- a/PermissionController/res/values/strings.xml +++ b/PermissionController/res/values/strings.xml @@ -2023,20 +2023,19 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo <string name="enhanced_confirmation_dialog_desc">For your security, this setting is currently unavailable.</string> <!--Title for dialog displayed to tell user that settings are blocked due to the phone state (such as being in a call with an unknown number) [CHAR LIMIT=50] --> - <string name="enhanced_confirmation_phone_state_dialog_title">Action not available while on a phone call</string> + <string name="enhanced_confirmation_phone_state_dialog_title">Can\u2019t complete action during call</string> <!--Content for dialog displayed to tell user that settings are blocked due to the phone state (such as being in a call with an unknown number) [CHAR LIMIT=NONE] --> <string name="enhanced_confirmation_phone_state_dialog_desc"><xliff:g id="setting_description" example="allowing apps to install other apps">%1$s</xliff:g>\n\n - Scammers often request this type of action during phone call conversations, so it\u2019s blocked to protect you. If you are being guided to take this action - by someone you don\u2019t know, it might be a scam.</string> + This setting is blocked to protect your device and data</string> <!--Content explaining that the "install other apps" setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix">Allowing apps to install other apps is not allowed during a phone call.</string> + <string name="enhanced_confirmation_phone_state_dialog_install_desc_prefix">Scammers may try to install harmful apps by asking you to install unknown apps from a new source.</string> <!--Content explaining that the "enable accessibility service" setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix">Giving an app access to accessibility is not allowed during a phone call.</string> + <string name="enhanced_confirmation_phone_state_dialog_a11y_desc_prefix">Scammers may try to take control of your device by asking you to allow accessibility access for an app.</string> <!--Content explaining that a generic setting is blocked due to the phone state in a dialog displayed to the user [CHAR LIMIT=NONE] --> - <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix">Enabling this setting is not allowed during a phone call.</string> + <string name="enhanced_confirmation_phone_state_dialog_generic_desc_prefix">Scammers may attempt to harm your device with this setting.</string> <!--Title for dialog displayed to tell user that permissions are blocked by setting restrictions [CHAR LIMIT=50] --> <string name="enhanced_confirmation_dialog_title_permission">App was denied access to <xliff:g id="permission_name" example="contacts">%1$s</xliff:g></string> diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml index 7963e7026..72e1d9654 100644 --- a/PermissionController/res/xml/roles.xml +++ b/PermissionController/res/xml/roles.xml @@ -1931,7 +1931,6 @@ <permission name="android.permission.ACCESS_FINE_LOCATION" /> <permission name="android.permission.READ_MEDIA_IMAGES" /> <permission name="android.permission.READ_MEDIA_VIDEO" /> - <permission name="android.permission.READ_GLOBAL_APP_SEARCH_DATA" /> </permissions> </role> diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java index 5109e505b..64682ba79 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java +++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java @@ -50,6 +50,7 @@ import com.android.role.controller.util.CollectionUtils; import com.android.role.controller.util.PackageUtils; import com.android.role.controller.util.RoleFlags; import com.android.role.controller.util.RoleManagerCompat; +import com.android.role.controller.util.SignedPackageUtils; import com.android.role.controller.util.UserUtils; import java.lang.annotation.Retention; @@ -84,10 +85,6 @@ public class Role { private static final String PACKAGE_NAME_ANDROID_SYSTEM = "android"; - private static final String DEFAULT_HOLDER_SEPARATOR = ";"; - - private static final String CERTIFICATE_SEPARATOR = ":"; - @Retention(RetentionPolicy.SOURCE) @IntDef({ EXCLUSIVITY_NONE, @@ -560,69 +557,11 @@ public class Role { } if (isExclusive()) { - String packageName = getQualifiedDefaultHolderPackageNameAsUser(defaultHolders, user, - context); - if (packageName == null) { - return Collections.emptyList(); - } - return Collections.singletonList(packageName); - } else { - List<String> packageNames = new ArrayList<>(); - for (String defaultHolder : defaultHolders.split(DEFAULT_HOLDER_SEPARATOR)) { - String packageName = getQualifiedDefaultHolderPackageNameAsUser(defaultHolder, - user, context); - if (packageName != null) { - packageNames.add(packageName); - } - } - return packageNames; - } - } - - @Nullable - private String getQualifiedDefaultHolderPackageNameAsUser(@NonNull String defaultHolder, - @NonNull UserHandle user, @NonNull Context context) { - String packageName; - byte[] certificate; - int certificateSeparatorIndex = defaultHolder.indexOf(CERTIFICATE_SEPARATOR); - if (certificateSeparatorIndex != -1) { - packageName = defaultHolder.substring(0, certificateSeparatorIndex); - String certificateString = defaultHolder.substring(certificateSeparatorIndex + 1); - try { - certificate = new Signature(certificateString).toByteArray(); - } catch (IllegalArgumentException e) { - Log.w(LOG_TAG, "Cannot parse signing certificate: " + defaultHolder, e); - return null; - } - } else { - packageName = defaultHolder; - certificate = null; - } - - if (certificate != null) { - Context userContext = UserUtils.getUserContext(context, user); - PackageManager userPackageManager = userContext.getPackageManager(); - if (!userPackageManager.hasSigningCertificate(packageName, certificate, - PackageManager.CERT_INPUT_SHA256)) { - Log.w(LOG_TAG, "Default holder doesn't have required signing certificate: " - + defaultHolder); - return null; - } + return CollectionUtils.singletonOrEmpty( + SignedPackageUtils.getPackageNameAsUser(defaultHolders, user, context)); } else { - ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, - user, context); - if (applicationInfo == null) { - Log.w(LOG_TAG, "Cannot get ApplicationInfo for default holder: " + packageName); - return null; - } - if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { - Log.w(LOG_TAG, "Default holder didn't specify a signing certificate and isn't a" - + " system app: " + packageName); - return null; - } + return SignedPackageUtils.getPackageNamesAsUser(defaultHolders, user, context); } - - return packageName; } /** diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java index cbffd451a..512015972 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java +++ b/PermissionController/role-controller/java/com/android/role/controller/util/PackageUtils.java @@ -57,7 +57,7 @@ public final class PackageUtils { } /** - * Retrieve if a package is a system package. + * Check whether a package is a system package. * * @param packageName the name of the package * @param user the user of the package @@ -93,4 +93,22 @@ public final class PackageUtils { return null; } } + + /** + * Check whether a package has a signing certificate. + * + * @param packageName the name of the package + * @param certificate the signing certificate + * @param user the user of the package + * @param context the {@code Context} to retrieve system services + * + * @return whether the package has the signing certificate. + */ + public static boolean hasSigningCertificateAsUser(@NonNull String packageName, + @NonNull byte[] certificate, @NonNull UserHandle user, @NonNull Context context) { + Context userContext = UserUtils.getUserContext(context, user); + PackageManager userPackageManager = userContext.getPackageManager(); + return userPackageManager.hasSigningCertificate(packageName, certificate, + PackageManager.CERT_INPUT_SHA256); + } } diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackage.java b/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackage.java new file mode 100644 index 000000000..a3869b349 --- /dev/null +++ b/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackage.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.role.controller.util; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.os.UserHandle; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * A package name with an optional signing certificate. + */ +public class SignedPackage { + + private static final String LOG_TAG = SignedPackage.class.getSimpleName(); + + private static final String SIGNED_PACKAGE_SEPARATOR = ";"; + private static final String CERTIFICATE_SEPARATOR = ":"; + + /** + * The name of the package. + */ + @NonNull + private final String mPackageName; + + /** + * The signing certificate of the package. + */ + @Nullable + private final byte[] mCertificate; + + public SignedPackage(@NonNull String packageName, @Nullable byte[] certificate) { + mPackageName = packageName; + mCertificate = certificate; + } + + @NonNull + public String getPackageName() { + return mPackageName; + } + + @Nullable + public byte[] getCertificate() { + return mCertificate; + } + + /** + * Parse a {@link SignedPackage} from a string input. + * + * @param input the package name, optionally followed by a colon and a signing certificate + * digest if it's not a system app + * + * @return the parsed {@link SignedPackage}, or {@code null} if the input is invalid + */ + @Nullable + public static SignedPackage parse(@NonNull String input) { + String packageName; + byte[] certificate; + int certificateSeparatorIndex = input.indexOf(CERTIFICATE_SEPARATOR); + if (certificateSeparatorIndex != -1) { + packageName = input.substring(0, certificateSeparatorIndex); + String certificateString = input.substring(certificateSeparatorIndex + 1); + try { + certificate = new Signature(certificateString).toByteArray(); + } catch (IllegalArgumentException e) { + Log.w(LOG_TAG, "Cannot parse signing certificate: " + input, e); + return null; + } + } else { + packageName = input; + certificate = null; + } + return new SignedPackage(packageName, certificate); + } + + /** + * Parse a list of {@link SignedPackage}s from a string input. + * + * @param input the package names, each optionally followed by a colon and a signing certificate + * digest if it's not a system app + * + * @return the parsed list of valid {@link SignedPackage}s + */ + @NonNull + public static List<SignedPackage> parseList(@NonNull String input) { + if (TextUtils.isEmpty(input)) { + return Collections.emptyList(); + } + List<SignedPackage> signedPackages = new ArrayList<>(); + for (String signedPackageInput : input.split(SIGNED_PACKAGE_SEPARATOR)) { + SignedPackage signedPackage = parse(signedPackageInput); + if (signedPackage != null) { + signedPackages.add(signedPackage); + } + } + return signedPackages; + } + + /* + * Checks whether this signed package is available, i.e. it is installed, and either has the + * specified signing certificate or is a system app if no signing certificate is specified. + * + * @param user the user of the package + * @param context the {@code Context} to retrieve system services + * + * @return whether this signed package is available + */ + public boolean isAvailableAsUser(@NonNull UserHandle user, @NonNull Context context) { + if (mCertificate != null) { + if (!PackageUtils.hasSigningCertificateAsUser(mPackageName, mCertificate, user, + context)) { + Log.w(LOG_TAG, "Package doesn't have required signing certificate: " + + mPackageName); + return false; + } + } else { + ApplicationInfo applicationInfo = + PackageUtils.getApplicationInfoAsUser(mPackageName, user, context); + if (applicationInfo == null) { + Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + mPackageName); + return false; + } + if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + Log.w(LOG_TAG, "Package didn't specify a signing certificate and isn't a" + + " system app: " + mPackageName); + return false; + } + } + return true; + } +} diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackageUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackageUtils.java new file mode 100644 index 000000000..817c31c5f --- /dev/null +++ b/PermissionController/role-controller/java/com/android/role/controller/util/SignedPackageUtils.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.role.controller.util; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.UserHandle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utility methods about {@link SignedPackage}. + */ +public final class SignedPackageUtils { + + private SignedPackageUtils() {} + + /** + * Get a list of package names from a string input for {@link SignedPackage}s. + * <p> + * This method only returns packages that are + * {@link SignedPackage#isAvailableAsUser(UserHandle, Context) available}. + * + * @param input the string input + * @param user the user of the packages + * @param context the {@code Context} to retrieve system services + * + * @return the package names + */ + @NonNull + public static List<String> getPackageNamesAsUser(@NonNull String input, + @NonNull UserHandle user, @NonNull Context context) { + List<SignedPackage> signedPackages = SignedPackage.parseList(input); + List<String> packageNames = new ArrayList<>(); + int signedPackagesSize = signedPackages.size(); + for (int i = 0; i < signedPackagesSize; i++) { + SignedPackage signedPackage = signedPackages.get(i); + if (signedPackage.isAvailableAsUser(user, context)) { + packageNames.add(signedPackage.getPackageName()); + } + } + return packageNames; + } + + /** + * Get a package name from a string input for a {@link SignedPackage}. + * <p> + * This method only returns a package if it is + * {@link SignedPackage#isAvailableAsUser(UserHandle, Context) available}. + * + * @param input the string input + * @param user the user of the package + * @param context the {@code Context} to retrieve system services + * + * @return the package name, or {@code null} otherwise + */ + @Nullable + public static String getPackageNameAsUser(@NonNull String input, @NonNull UserHandle user, + @NonNull Context context) { + SignedPackage signedPackage = SignedPackage.parse(input); + if (signedPackage == null || !signedPackage.isAvailableAsUser(user, context)) { + return null; + } + return signedPackage.getPackageName(); + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt index 4c698cda3..2428abb4a 100644 --- a/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/incident/wear/WearConfirmationScreen.kt @@ -30,10 +30,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.wear.compose.material.CircularProgressIndicator -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionConfirmationDialog +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme @Composable fun WearConfirmationScreen(viewModel: WearConfirmationActivityViewModel) { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt index 394cb3eb7..ad356d5f7 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/data/AppPermGroupUiInfoLiveData.kt @@ -18,6 +18,7 @@ package com.android.permissioncontroller.permission.data import android.Manifest import android.Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED +import android.Manifest.permission_group.READ_MEDIA_VISUAL import android.Manifest.permission_group.STORAGE import android.app.AppOpsManager import android.app.Application @@ -66,13 +67,8 @@ private constructor( private val isHealth = Utils.isHealthPermissionGroup(permGroupName) init { - isSpecialLocation = - LocationUtils.isLocationGroupAndProvider(app, permGroupName, packageName) || - LocationUtils.isLocationGroupAndControllerExtraPackage( - app, - permGroupName, - packageName - ) + isSpecialLocation = LightAppPermGroupLiveData + .isSpecialLocationGranted(app, packageName, permGroupName, user) != null addSource(packageInfoLiveData) { update() } @@ -258,9 +254,14 @@ private constructor( allPermInfos: Map<String, LightPermInfo>, pkg: LightPackageInfo ): PermGrantState { - val specialLocationState = getIsSpecialLocationState() + val specialLocationState = LightAppPermGroupLiveData + .isSpecialLocationGranted(app, packageName, permGroupName, user) + val specialFixedStorage = LightAppPermGroupLiveData + .isSpecialFixedStorageGranted(app, packageName, permGroupName, pkg.uid) if (isStorage && isFullFilesAccessGranted(pkg)) { return PermGrantState.PERMS_ALLOWED + } else if (permGroupName == READ_MEDIA_VISUAL && specialFixedStorage) { + return PermGrantState.PERMS_ALLOWED } var hasPermWithBackground = false @@ -332,29 +333,6 @@ private constructor( return PermGrantState.PERMS_DENIED } - private fun getIsSpecialLocationState(): Boolean? { - if (!isSpecialLocation) { - return null - } - - val userContext = Utils.getUserContext(app, user) - if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) { - return LocationUtils.isLocationEnabled(userContext) - } - // The permission of the extra location controller package is determined by the - // status of the controller package itself. - if ( - LocationUtils.isLocationGroupAndControllerExtraPackage( - userContext, - permGroupName, - packageName - ) - ) { - return LocationUtils.isExtraLocationControllerPackageEnabled(userContext) - } - return null - } - private fun isFullFilesAccessGranted(pkg: LightPackageInfo): Boolean { val packageState = if (!FullStoragePermissionAppsLiveData.isStale) { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt index 67b765097..d66d6ec6c 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/data/LightAppPermGroupLiveData.kt @@ -16,7 +16,13 @@ package com.android.permissioncontroller.permission.data +import android.Manifest.permission_group.READ_MEDIA_VISUAL +import android.Manifest.permission_group.STORAGE +import android.app.AppOpsManager +import android.app.AppOpsManager.MODE_ALLOWED +import android.app.AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES import android.app.Application +import android.app.role.RoleManager import android.content.pm.PackageManager import android.content.pm.PermissionInfo import android.os.Build @@ -121,19 +127,6 @@ private constructor( LightPermission(packageInfo, permInfo, permState, foregroundPerms) } - // Determine if this app permission group is a special location package or provider - var specialLocationGrant: Boolean? = null - val userContext = Utils.getUserContext(app, user) - if (LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName)) { - specialLocationGrant = LocationUtils.isLocationEnabled(userContext) - } else if ( - LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName) - ) { - // The permission of the extra location controller package is determined by the status - // of the controller package itself. - specialLocationGrant = - LocationUtils.isExtraLocationControllerPackageEnabled(userContext) - } val hasInstallToRuntimeSplit = hasInstallToRuntimeSplit(packageInfo, permissionMap) value = @@ -142,7 +135,8 @@ private constructor( permGroup.groupInfo, permissionMap, hasInstallToRuntimeSplit, - specialLocationGrant + isSpecialLocationGranted(app, packageName, permGroupName, user), + isSpecialFixedStorageGranted(app, packageName, permGroupName, packageInfo.uid) ) } @@ -234,5 +228,56 @@ private constructor( deviceId ) } + + private const val SYSTEM_GALLERY_ROLE_NAME = "android.app.role.SYSTEM_GALLERY" + + // Returns true if this app is the location provider or location extra package, and location + // access is granted, false if it is the provider/extra, and location is not granted, and + // null if it is not a special package + fun isSpecialLocationGranted( + app: Application, + packageName: String, + permGroupName: String, + user: UserHandle + ): Boolean? { + val userContext = Utils.getUserContext(app, user) + return if ( + LocationUtils.isLocationGroupAndProvider(userContext, permGroupName, packageName) + ) { + LocationUtils.isLocationEnabled(userContext) + } else if ( + LocationUtils.isLocationGroupAndControllerExtraPackage(app, permGroupName, packageName) + ) { + // The permission of the extra location controller package is determined by the status + // of the controller package itself. + LocationUtils.isExtraLocationControllerPackageEnabled(userContext) + } else { + null + } + } + + // Gallery role is static, so we only need to get the set gallery app once + private val systemGalleryApps: List<String> by lazy { + val roleManager = PermissionControllerApplication.get() + .getSystemService(RoleManager::class.java) ?: return@lazy emptyList() + roleManager.getRoleHolders(SYSTEM_GALLERY_ROLE_NAME) + } + + fun isSpecialFixedStorageGranted( + app: Application, + packageName: String, + permGroupName: String, + uid: Int + ): Boolean { + if (permGroupName != READ_MEDIA_VISUAL && permGroupName != STORAGE) { + return false + } + if (packageName !in systemGalleryApps) { + return false + } + // This is the storage group, and the gallery app. Check the write media app op + val appOps = app.getSystemService(AppOpsManager::class.java) + return appOps.checkOpNoThrow(OPSTR_WRITE_MEDIA_IMAGES, uid, packageName) == MODE_ALLOWED + } } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt deleted file mode 100644 index a3fc40232..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/data/v31/AllLightHistoricalPackageOpsLiveData.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.permissioncontroller.permission.data.v31 - -import android.app.AppOpsManager -import android.app.AppOpsManager.HISTORY_FLAG_DISCRETE -import android.app.AppOpsManager.HISTORY_FLAG_GET_ATTRIBUTION_CHAINS -import android.app.AppOpsManager.HistoricalOps -import android.app.AppOpsManager.HistoricalOpsRequest -import android.app.AppOpsManager.OP_FLAG_SELF -import android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED -import android.app.Application -import android.os.UserHandle -import android.os.UserManager -import com.android.modules.utils.build.SdkLevel -import com.android.permissioncontroller.permission.data.SmartAsyncMediatorLiveData -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps -import java.util.concurrent.TimeUnit -import kotlin.coroutines.suspendCoroutine -import kotlinx.coroutines.Job - -/** - * LiveData class tracking [LightHistoricalPackageOps] for all packages on the device and for the - * provided app ops. - * - * App ops data is retrieved from [AppOpsManager] and is updated whenever app ops data changes are - * heard. - */ -class AllLightHistoricalPackageOpsLiveData(app: Application, val opNames: Set<String>) : - SmartAsyncMediatorLiveData<Map<Pair<String, UserHandle>, LightHistoricalPackageOps>>(), - AppOpsManager.OnOpActiveChangedListener, - AppOpsManager.OnOpNotedListener, - AppOpsManager.OnOpChangedListener { - - private val appOpsManager = app.getSystemService(AppOpsManager::class.java)!! - private val userManager = app.getSystemService(UserManager::class.java)!! - - override fun onActive() { - super.onActive() - - opNames.forEach { opName -> - // TODO(b/262035952): We watch each active op individually as startWatchingActive only - // registers the callback if all ops are valid. Fix this behavior so if one op is - // invalid it doesn't affect the other ops. - try { - appOpsManager.startWatchingActive(arrayOf(opName), { it.run() }, this) - } catch (ignored: IllegalArgumentException) { - // Older builds may not support all requested app ops. - } - - try { - appOpsManager.startWatchingMode(opName, /* all packages */ null, this) - } catch (ignored: IllegalArgumentException) { - // Older builds may not support all requested app ops. - } - - if (SdkLevel.isAtLeastU()) { - try { - appOpsManager.startWatchingNoted(arrayOf(opName), this) - } catch (ignored: IllegalArgumentException) { - // Older builds may not support all requested app ops. - } - } - } - } - - override fun onInactive() { - super.onInactive() - - appOpsManager.stopWatchingActive(this) - appOpsManager.stopWatchingMode(this) - } - - override suspend fun loadDataAndPostValue(job: Job) { - if (job.isCancelled) { - return - } - - val allLightHistoricalPackageOps = - mutableMapOf<Pair<String, UserHandle>, LightHistoricalPackageOps>() - - val endTimeMillis = System.currentTimeMillis() - val beginTimeMillis = endTimeMillis - TimeUnit.DAYS.toMillis(7) - - val allProfilesInCurrentUser = userManager.userProfiles - - val request = - HistoricalOpsRequest.Builder(beginTimeMillis, endTimeMillis) - .setFlags(OP_FLAG_SELF or OP_FLAG_TRUSTED_PROXIED) - .setHistoryFlags(HISTORY_FLAG_DISCRETE or HISTORY_FLAG_GET_ATTRIBUTION_CHAINS) - .build() - - val historicalOps = suspendCoroutine { - appOpsManager.getHistoricalOps(request, { it.run() }) { ops: HistoricalOps -> - it.resumeWith(Result.success(ops)) - } - } - - for (i in 0 until historicalOps.uidCount) { - val historicalUidOps = historicalOps.getUidOpsAt(i) - val userHandle = UserHandle.getUserHandleForUid(historicalUidOps.uid) - if (userHandle !in allProfilesInCurrentUser) { - continue - } - for (j in 0 until historicalUidOps.packageCount) { - val historicalPackageOps = historicalUidOps.getPackageOpsAt(j) - allLightHistoricalPackageOps[Pair(historicalPackageOps.packageName, userHandle)] = - LightHistoricalPackageOps(historicalPackageOps, userHandle, opNames) - } - } - - postValue(allLightHistoricalPackageOps) - } - - override fun onOpChanged(op: String?, packageName: String?) { - update() - } - - override fun onOpActiveChanged(op: String, uid: Int, packageName: String, active: Boolean) { - update() - } - - override fun onOpNoted( - code: String, - uid: Int, - packageName: String, - attributionTag: String?, - flags: Int, - result: Int - ) { - update() - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt index 61a604de8..18f4ce203 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/model/livedatatypes/LightAppPermGroup.kt @@ -35,19 +35,24 @@ import com.android.permissioncontroller.permission.utils.Utils * @param specialLocationGrant If this package is the location provider, or the extra location * package, then the grant state of the group is not determined by the grant state of individual * permissions, but by other system properties + * @param specialFixedStorageGrant If this package holds the SYSTEM_GALLERY role, and has the + * WRITE_MEDIA_IMAGES app op granted, then we should show the grant state of the storage + * permissions as system fixed and granted. + * */ data class LightAppPermGroup( val packageInfo: LightPackageInfo, val permGroupInfo: LightPermGroupInfo, val allPermissions: Map<String, LightPermission>, val hasInstallToRuntimeSplit: Boolean, - val specialLocationGrant: Boolean? + val specialLocationGrant: Boolean?, + val specialFixedStorageGrant: Boolean, ) { constructor( pI: LightPackageInfo, pGI: LightPermGroupInfo, perms: Map<String, LightPermission> - ) : this(pI, pGI, perms, false, null) + ) : this(pI, pGI, perms, false, null, false) /** All unrestricted permissions. Usually restricted permissions are ignored */ val permissions: Map<String, LightPermission> = @@ -83,7 +88,8 @@ data class LightAppPermGroup( permissions.filter { it.key in foregroundPermNames }, packageInfo, isPlatformPermissionGroup, - specialLocationGrant + specialLocationGrant, + specialFixedStorageGrant ) val background = @@ -91,7 +97,8 @@ data class LightAppPermGroup( permissions.filter { it.key in backgroundPermNames }, packageInfo, isPlatformPermissionGroup, - specialLocationGrant + specialLocationGrant, + specialFixedStorageGrant ) /** Whether or not this App Permission Group has a permission which has a background mode */ @@ -167,18 +174,20 @@ data class LightAppPermGroup( * contained in the full group * @param isPlatformPermissionGroup Whether this is a platform permission group * @param specialLocationGrant Whether this is a special location package + * @param specialFixedStorageGrant Whether this is a special storage grant */ data class AppPermSubGroup internal constructor( private val permissions: Map<String, LightPermission>, private val packageInfo: LightPackageInfo, private val isPlatformPermissionGroup: Boolean, - private val specialLocationGrant: Boolean? + private val specialLocationGrant: Boolean?, + private val specialFixedStorageGrant: Boolean ) { /** Whether any of this App Permission SubGroup's permissions are granted */ val isGranted = specialLocationGrant - ?: permissions.any { + ?: specialFixedStorageGrant || permissions.any { val mayGrantByPlatformOrSystem = !isPlatformPermissionGroup || it.value.isPlatformOrSystem it.value.isGranted && mayGrantByPlatformOrSystem @@ -216,7 +225,7 @@ data class LightAppPermGroup( val isPolicyFixed = permissions.any { it.value.isPolicyFixed } /** Whether any of this App Permission Subgroup's permissions are fixed by the system */ - val isSystemFixed = permissions.any { it.value.isSystemFixed } + val isSystemFixed = permissions.any { it.value.isSystemFixed } || specialFixedStorageGrant /** Whether any of this App Permission Subgroup's permissions are fixed by the user */ val isUserFixed = permissions.any { it.value.isUserFixed } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt index 85145f346..184c37921 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/service/RuntimePermissionsUpgradeController.kt @@ -503,7 +503,8 @@ object RuntimePermissionsUpgradeController { bgApp.permGroupInfo, allPermissionsWithxemption, bgApp.hasInstallToRuntimeSplit, - bgApp.specialLocationGrant + bgApp.specialLocationGrant, + bgApp.specialFixedStorageGrant, ) } @@ -683,7 +684,8 @@ object RuntimePermissionsUpgradeController { bgSensorsGroup.permGroupInfo, allPermissionsWithExemption, bgSensorsGroup.hasInstallToRuntimeSplit, - bgSensorsGroup.specialLocationGrant + bgSensorsGroup.specialLocationGrant, + bgSensorsGroup.specialFixedStorageGrant, ) // Grant the background permission only if foreground permission is granted. diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt index 8edd39913..2ecf40ce2 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/dashboard/AutoPermissionUsageDetailsFragment.kt @@ -35,7 +35,6 @@ import com.android.permissioncontroller.R import com.android.permissioncontroller.auto.AutoSettingsFrameFragment import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity import com.android.permissioncontroller.permission.ui.auto.AutoDividerPreference -import com.android.permissioncontroller.permission.ui.model.v31.BasePermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.AppPermissionAccessUiInfo import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel @@ -80,7 +79,7 @@ class AutoPermissionUsageDetailsFragment : AutoSettingsFrameFragment() { private val SESSION_ID_KEY = (AutoPermissionUsageFragment::class.java.name + KEY_SESSION_ID) - private lateinit var usageViewModel: BasePermissionUsageDetailsViewModel + private lateinit var usageViewModel: PermissionUsageDetailsViewModel private lateinit var filterGroup: String private var showSystem = false @@ -119,11 +118,10 @@ class AutoPermissionUsageDetailsFragment : AutoSettingsFrameFragment() { val factory = PermissionUsageDetailsViewModel.PermissionUsageDetailsViewModelFactory( PermissionControllerApplication.get(), - this, filterGroup, ) usageViewModel = - ViewModelProvider(this, factory)[BasePermissionUsageDetailsViewModel::class.java] + ViewModelProvider(this, factory)[PermissionUsageDetailsViewModel::class.java] usageViewModel.getPermissionUsagesDetailsInfoUiLiveData().observe(this, this::updateUI) } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java index c1902fb57..af204d7d4 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionsFrameFragment.java @@ -98,9 +98,6 @@ public abstract class PermissionsFrameFragment extends PreferenceFragmentCompat com.android.settingslib.widget.progressbar.R.id.progress_bar_background); setProgressBarVisible(false); getListView().setFocusable(false); - if (SdkLevel.isAtLeastV()) { - rootView.setFitsSystemWindows(true); - } return rootView; } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java index 3a904c466..9078f1a0a 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/v31/PermissionUsageDetailsFragment.java @@ -54,7 +54,7 @@ import com.android.permissioncontroller.PermissionControllerApplication; import com.android.permissioncontroller.R; import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity; import com.android.permissioncontroller.permission.ui.handheld.SettingsWithLargeHeader; -import com.android.permissioncontroller.permission.ui.model.v31.BasePermissionUsageDetailsViewModel; +import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel; import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.AppPermissionAccessUiInfo; import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState; import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsViewModelFactory; @@ -89,7 +89,7 @@ public class PermissionUsageDetailsFragment extends SettingsWithLargeHeader { private MenuItem mShow7DaysDataMenu; private MenuItem mShow24HoursDataMenu; - private BasePermissionUsageDetailsViewModel mViewModel; + private PermissionUsageDetailsViewModel mViewModel; private long mSessionId; @@ -103,9 +103,9 @@ public class PermissionUsageDetailsFragment extends SettingsWithLargeHeader { } PermissionUsageDetailsViewModelFactory factory = new PermissionUsageDetailsViewModelFactory( - PermissionControllerApplication.get(), this, mPermissionGroup); + PermissionControllerApplication.get(), mPermissionGroup); mViewModel = - new ViewModelProvider(this, factory).get(BasePermissionUsageDetailsViewModel.class); + new ViewModelProvider(this, factory).get(PermissionUsageDetailsViewModel.class); if (savedInstanceState != null) { mSessionId = savedInstanceState.getLong(SESSION_ID_KEY); diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/BasePermissionUsageDetailsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/BasePermissionUsageDetailsViewModel.kt deleted file mode 100644 index 64c5c6927..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/BasePermissionUsageDetailsViewModel.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.permissioncontroller.permission.ui.model.v31 - -import android.app.Application -import android.graphics.drawable.Drawable -import android.os.UserHandle -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.LiveData -import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.handheld.v31.getDurationUsedStr -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.CLUSTER_SPACING_MINUTES -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState -import com.android.permissioncontroller.permission.utils.KotlinUtils -import java.util.concurrent.TimeUnit - -abstract class BasePermissionUsageDetailsViewModel(val app: Application) : AndroidViewModel(app) { - abstract fun getPermissionUsagesDetailsInfoUiLiveData(): LiveData<PermissionUsageDetailsUiState> - - abstract fun getShowSystem(): Boolean - - abstract val showSystemLiveData: LiveData<Boolean> - - abstract fun getShow7Days(): Boolean - - abstract fun updateShowSystemAppsToggle(showSystem: Boolean) - - abstract fun updateShow7DaysToggle(show7Days: Boolean) - - private val packageIconCache: MutableMap<Pair<String, UserHandle>, Drawable> = mutableMapOf() - private val packageLabelCache: MutableMap<String, String> = mutableMapOf() - - /** - * Returns the label for the provided package name, by first searching the cache otherwise - * retrieving it from the app's [android.content.pm.ApplicationInfo]. - */ - fun getPackageLabel(packageName: String, user: UserHandle): String { - if (packageLabelCache.containsKey(packageName)) { - return requireNotNull(packageLabelCache[packageName]) - } - val packageLabel = getPackageLabel(app, packageName, user) - packageLabelCache[packageName] = packageLabel - return packageLabel - } - - open fun getPackageLabel(app: Application, packageName: String, user: UserHandle): String { - return KotlinUtils.getPackageLabel(app, packageName, user) - } - - /** - * Returns the icon for the provided package name and user, by first searching the cache - * otherwise retrieving it from the app's [android.content.pm.ApplicationInfo]. - */ - fun getBadgedPackageIcon(packageName: String, userHandle: UserHandle): Drawable? { - val packageNameWithUser: Pair<String, UserHandle> = Pair(packageName, userHandle) - if (packageIconCache.containsKey(packageNameWithUser)) { - return requireNotNull(packageIconCache[packageNameWithUser]) - } - val packageIcon = getBadgedPackageIcon(app, packageName, userHandle) - if (packageIcon != null) packageIconCache[packageNameWithUser] = packageIcon - - return packageIcon - } - - open fun getBadgedPackageIcon( - app: Application, - packageName: String, - user: UserHandle - ): Drawable? { - return KotlinUtils.getBadgedPackageIcon(app, packageName, user) - } - - fun getDurationSummary(durationMs: Long): String? { - // Only show the duration summary if it is at least (CLUSTER_SPACING_MINUTES + 1) minutes. - // Displaying a time that is shorter than the cluster granularity - // (CLUSTER_SPACING_MINUTES) will not convey useful information. - if (durationMs >= TimeUnit.MINUTES.toMillis(CLUSTER_SPACING_MINUTES + 1)) { - return getDurationUsedStr(app, durationMs) - } - return null - } - - fun buildUsageSummary( - subAttributionLabel: String?, - proxyPackageLabel: String?, - durationSummary: String? - ): String? { - val subTextStrings: MutableList<String> = mutableListOf() - subAttributionLabel?.let { subTextStrings.add(subAttributionLabel) } - proxyPackageLabel?.let { subTextStrings.add(it) } - durationSummary?.let { subTextStrings.add(it) } - return when (subTextStrings.size) { - 3 -> - app.getString( - R.string.history_preference_subtext_3, - subTextStrings[0], - subTextStrings[1], - subTextStrings[2] - ) - 2 -> - app.getString( - R.string.history_preference_subtext_2, - subTextStrings[0], - subTextStrings[1] - ) - 1 -> subTextStrings[0] - else -> null - } - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt index 497e5cc35..ad21ab220 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 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. @@ -13,677 +13,288 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -@file:Suppress("DEPRECATION") package com.android.permissioncontroller.permission.ui.model.v31 import android.Manifest import android.app.AppOpsManager +import android.app.AppOpsManager.OPSTR_EMERGENCY_LOCATION import android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA import android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE import android.app.Application -import android.app.role.RoleManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager -import android.content.res.Resources import android.graphics.drawable.Drawable import android.location.LocationManager import android.os.Build -import android.os.Bundle import android.os.UserHandle -import android.os.UserManager import android.permission.flags.Flags -import android.util.Log import androidx.annotation.RequiresApi -import androidx.lifecycle.AbstractSavedStateViewModelFactory +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel -import androidx.savedstate.SavedStateRegistryOwner +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.application +import androidx.lifecycle.asLiveData +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.CreationExtras import com.android.modules.utils.build.SdkLevel import com.android.permissioncontroller.DeviceUtils import com.android.permissioncontroller.R +import com.android.permissioncontroller.appops.data.repository.v31.AppOpRepository import com.android.permissioncontroller.permission.compat.IntentCompat -import com.android.permissioncontroller.permission.data.AppPermGroupUiInfoLiveData -import com.android.permissioncontroller.permission.data.LightPackageInfoLiveData -import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData -import com.android.permissioncontroller.permission.data.get -import com.android.permissioncontroller.permission.data.v31.AllLightHistoricalPackageOpsLiveData -import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo -import com.android.permissioncontroller.permission.model.livedatatypes.v31.AppPermissionId -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps.AppPermissionDiscreteAccesses -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps.AttributedAppPermissionDiscreteAccesses -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps.Companion.NO_ATTRIBUTION_TAG -import com.android.permissioncontroller.permission.model.livedatatypes.v31.LightHistoricalPackageOps.DiscreteAccess +import com.android.permissioncontroller.permission.data.repository.v31.PermissionRepository +import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModel +import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModelWrapper +import com.android.permissioncontroller.permission.domain.usecase.v31.GetPermissionGroupUsageDetailsUseCase import com.android.permissioncontroller.permission.ui.handheld.v31.getDurationUsedStr -import com.android.permissioncontroller.permission.ui.handheld.v31.shouldShowSubattributionInPermissionsDashboard import com.android.permissioncontroller.permission.utils.PermissionMapping -import com.android.permissioncontroller.permission.utils.Utils -import com.android.permissioncontroller.permission.utils.v31.SubattributionUtils +import com.android.permissioncontroller.pm.data.repository.v31.PackageRepository +import com.android.permissioncontroller.role.data.repository.v31.RoleRepository +import com.android.permissioncontroller.user.data.repository.v31.UserRepository import java.time.Instant import java.util.Objects import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit.DAYS +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.stateIn -/** [ViewModel] for the Permission Usage Details page. */ -@RequiresApi(Build.VERSION_CODES.S) class PermissionUsageDetailsViewModel( - private val application: Application, + app: Application, + private val getPermissionUsageDetailsUseCase: GetPermissionGroupUsageDetailsUseCase, private val state: SavedStateHandle, private val permissionGroup: String, -) : BasePermissionUsageDetailsViewModel(application) { - - val allLightHistoricalPackageOpsLiveData = - AllLightHistoricalPackageOpsLiveData(application, opNames) - private val appPermGroupUiInfoLiveDataList = - mutableMapOf<AppPermissionId, AppPermGroupUiInfoLiveData>() - private val lightPackageInfoLiveDataMap = - mutableMapOf<Pair<String, UserHandle>, LightPackageInfoLiveData>() - - override val showSystemLiveData = state.getLiveData(SHOULD_SHOW_SYSTEM_KEY, false) - val show7DaysLiveData = state.getLiveData(SHOULD_SHOW_7_DAYS_KEY, false) - - private val roleManager = - Utils.getSystemServiceSafe(application.applicationContext, RoleManager::class.java) - private val userManager = - Utils.getSystemServiceSafe(application.applicationContext, UserManager::class.java) + scope: CoroutineScope? = null, + private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default, + private val packageRepository: PackageRepository = PackageRepository.getInstance(app), +) : AndroidViewModel(app) { + private val coroutineScope = scope ?: viewModelScope + private val context = app + + private val packageIconCache: MutableMap<Pair<String, UserHandle>, Drawable> = mutableMapOf() + private val packageLabelCache: MutableMap<String, String> = mutableMapOf() + + private val showSystemFlow = MutableStateFlow(state[SHOULD_SHOW_SYSTEM_KEY] ?: false) + private val show7DaysFlow = MutableStateFlow(state[SHOULD_SHOW_7_DAYS_KEY] ?: false) + + private val permissionTimelineUsagesFlow: + StateFlow<PermissionTimelineUsageModelWrapper> by lazy { + getPermissionUsageDetailsUseCase(coroutineScope) + .flowOn(defaultDispatcher) + .stateIn( + coroutineScope, + SharingStarted.WhileSubscribed(5000), + PermissionTimelineUsageModelWrapper.Loading, + ) + } - /** Updates whether system app permissions usage should be displayed in the UI. */ - override fun updateShowSystemAppsToggle(showSystem: Boolean) { - if (showSystem != state[SHOULD_SHOW_SYSTEM_KEY]) { - state[SHOULD_SHOW_SYSTEM_KEY] = showSystem - } + @VisibleForTesting + val permissionUsageDetailsUiStateFlow: Flow<PermissionUsageDetailsUiState> by lazy { + combine(permissionTimelineUsagesFlow, showSystemFlow, show7DaysFlow) { + permissionTimelineUsages, + showSystem, + show7Days -> + permissionTimelineUsages.buildPermissionUsageDetailsUiInfo(showSystem, show7Days) + } + .flowOn(defaultDispatcher) } - /** Updates whether 7 days usage or 1 day usage should be displayed in the UI. */ - override fun updateShow7DaysToggle(show7Days: Boolean) { - if (show7Days != state[SHOULD_SHOW_7_DAYS_KEY]) { - state[SHOULD_SHOW_7_DAYS_KEY] = show7Days - } + fun getPermissionUsagesDetailsInfoUiLiveData(): LiveData<PermissionUsageDetailsUiState> { + return permissionUsageDetailsUiStateFlow.asLiveData( + context = coroutineScope.coroutineContext + ) } - /** Creates a [PermissionUsageDetailsUiState] containing all information to render the UI. */ - fun buildPermissionUsageDetailsUiInfo(): PermissionUsageDetailsUiState { - val showSystem: Boolean = state[SHOULD_SHOW_SYSTEM_KEY] ?: false - val show7Days: Boolean = state[SHOULD_SHOW_7_DAYS_KEY] ?: false - val showPermissionUsagesDuration = - if (show7Days && DeviceUtils.isHandheld()) { - TIME_7_DAYS_DURATION - } else { - TIME_24_HOURS_DURATION - } + private fun PermissionTimelineUsageModelWrapper.buildPermissionUsageDetailsUiInfo( + showSystem: Boolean, + show7Days: Boolean, + ): PermissionUsageDetailsUiState { + if (this is PermissionTimelineUsageModelWrapper.Loading) { + return PermissionUsageDetailsUiState.Loading + } + val timelineUsageModels = + (this as PermissionTimelineUsageModelWrapper.Success).timelineUsageModels val startTime = - (System.currentTimeMillis() - showPermissionUsagesDuration).coerceAtLeast( + (System.currentTimeMillis() - getUsageDuration(show7Days)).coerceAtLeast( Instant.EPOCH.toEpochMilli() ) + val permissionTimelineUsageModels = + timelineUsageModels.filter { it.accessEndMillis > startTime } + val containsSystemUsages = permissionTimelineUsageModels.any { !it.isUserSensitive } + val result = + permissionTimelineUsageModels + .filter { showSystem || it.isUserSensitive } + .map { clusterOps -> + val durationSummaryLabel = + if (clusterOps.durationMillis > 0) { + getDurationSummary(clusterOps.durationMillis) + } else { + null + } + val proxyLabel = getProxyPackageLabel(clusterOps) + val isEmergencyLocationAccess = + isLocationByPassEnabled() && + clusterOps.opNames.any { it == OPSTR_EMERGENCY_LOCATION } + val subAttributionLabel = + if (isEmergencyLocationAccess) { + emergencyLocationAttributionLabel + } else { + clusterOps.attributionLabel + } + val showingSubAttribution = !subAttributionLabel.isNullOrEmpty() + val summary = + buildUsageSummary(subAttributionLabel, proxyLabel, durationSummaryLabel) + PermissionUsageDetailsViewModel.AppPermissionAccessUiInfo( + UserHandle.of(clusterOps.userId), + clusterOps.packageName, + getPackageLabel(clusterOps.packageName, UserHandle.of(clusterOps.userId)), + permissionGroup, + clusterOps.accessStartMillis, + clusterOps.accessEndMillis, + summary, + showingSubAttribution, + clusterOps.attributionTags ?: emptySet(), + getBadgedPackageIcon( + clusterOps.packageName, + UserHandle.of(clusterOps.userId), + ), + isEmergencyLocationAccess, + ) + } + .sortedBy { -1 * it.accessStartTime } return PermissionUsageDetailsUiState.Success( - buildAppPermissionAccessUiInfoList( - allLightHistoricalPackageOpsLiveData, - startTime, - showSystem - ), - containsSystemAppUsages(allLightHistoricalPackageOpsLiveData, startTime), + result, + containsSystemUsages, showSystem, - show7Days + show7Days, ) } - /** - * Returns whether the "show/hide system" toggle should be displayed in the UI for the provided - * [AllLightHistoricalPackageOpsLiveData]. - */ - private fun containsSystemAppUsages( - allLightHistoricalPackageOpsLiveData: AllLightHistoricalPackageOpsLiveData, - startTime: Long - ): Boolean { - return allLightHistoricalPackageOpsLiveData - .getLightHistoricalPackageOps() - ?.flatMap { - it.appPermissionDiscreteAccesses - .map { it.withLabel() } - .filterOutExemptAppPermissions(true) - .filterAccessesLaterThan(startTime) - } - ?.any { isAppPermissionSystem(it.appPermissionId) } ?: false + private val emergencyLocationAttributionLabel: String by lazy { + context.getString(R.string.privacy_dashboard_emergency_location_enforced_attribution_label) } - private fun isPermissionRequestedByApp(appPermissionId: AppPermissionId): Boolean { - val appRequestedPermissions = - lightPackageInfoLiveDataMap[ - Pair(appPermissionId.packageName, appPermissionId.userHandle)] - ?.value - ?.requestedPermissions ?: listOf() - - if ( - appPermissionId.permissionGroup == Manifest.permission_group.LOCATION && - appRequestedPermissions.contains(Manifest.permission.LOCATION_BYPASS) - ) { - return true - } + fun getShowSystem(): Boolean = showSystemFlow.value - return appRequestedPermissions.any { - PermissionMapping.getGroupOfPlatformPermission(it) == appPermissionId.permissionGroup - } - } + val showSystemLiveData = showSystemFlow.asLiveData(context = coroutineScope.coroutineContext) - private fun isAppPermissionSystem(appPermissionId: AppPermissionId): Boolean { - val appPermGroupUiInfo = appPermGroupUiInfoLiveDataList[appPermissionId]?.value - - if (appPermGroupUiInfo != null) { - return appPermGroupUiInfo.isSystem - } else - // The AppPermGroupUiInfo may be null if it has either not loaded yet or if the app has not - // requested any permissions from the permission group in question. - // The Telecom doesn't request microphone or camera permissions. However, telecom app may - // use these permissions and they are considered system app permissions, so we return true - // even if the AppPermGroupUiInfo is unavailable. - if ( - appPermissionId.packageName == TELECOM_PACKAGE && - (appPermissionId.permissionGroup == Manifest.permission_group.CAMERA || - appPermissionId.permissionGroup == Manifest.permission_group.MICROPHONE) - ) { - return true + fun getShow7Days(): Boolean = show7DaysFlow.value + + private fun getUsageDuration(show7Days: Boolean): Long { + return if (show7Days && DeviceUtils.isHandheld()) { + TIME_7_DAYS_DURATION + } else { + TIME_24_HOURS_DURATION } - return false } - /** - * Extracts access data from [AllLightHistoricalPackageOpsLiveData] and composes - * [AppPermissionAccessUiInfo]s to be displayed in the UI. - */ - private fun buildAppPermissionAccessUiInfoList( - allLightHistoricalPackageOpsLiveData: AllLightHistoricalPackageOpsLiveData, - startTime: Long, - showSystem: Boolean - ): List<AppPermissionAccessUiInfo> { - return allLightHistoricalPackageOpsLiveData - .getLightHistoricalPackageOps() - ?.filter { Utils.shouldShowInSettings(it.userHandle, userManager) } - ?.flatMap { it.clusterAccesses(startTime, showSystem) } - ?.map { it.buildAppPermissionAccessUiInfo() } - ?.sortedBy { -it.accessStartTime } ?: listOf() - } + private fun getProxyPackageLabel(accessCluster: PermissionTimelineUsageModel): String? = + accessCluster.proxyPackageName?.let { proxyPackageName -> + if (accessCluster.proxyUserId != null) { + getPackageLabel(proxyPackageName, UserHandle.of(accessCluster.proxyUserId)) + } else null + } - private fun LightHistoricalPackageOps.clusterAccesses( - startTime: Long, - showSystem: Boolean - ): List<AppPermissionDiscreteAccessCluster> { - return if (!shouldShowSubAttributionForApp(getLightPackageInfo(packageName, userHandle))) - this.clusterAccessesWithoutAttribution(startTime, showSystem) - else { - this.clusterAccessesWithAttribution(startTime, showSystem) + fun updateShowSystemAppsToggle(showSystem: Boolean) { + if (showSystem != state[SHOULD_SHOW_SYSTEM_KEY]) { + state[SHOULD_SHOW_SYSTEM_KEY] = showSystem } + showSystemFlow.compareAndSet(!showSystem, showSystem) } - /** - * Clusters accesses that are close enough together in time such that they can be displayed as a - * single access to the user. - * - * Accesses are clustered taking into account any app subattribution, so each cluster will - * pertain a particular attribution label. - */ - private fun LightHistoricalPackageOps.clusterAccessesWithAttribution( - startTime: Long, - showSystem: Boolean - ): List<AppPermissionDiscreteAccessCluster> = - this.attributedAppPermissionDiscreteAccesses - .flatMap { it.groupAccessesByLabel(getLightPackageInfo(packageName, userHandle)) } - .filterOutExemptAppPermissions(showSystem) - .filterAccessesLaterThan(startTime) - .flatMap { createAccessClusters(it) } - - /** - * Clusters accesses that are close enough together in time such that they can be displayed as a - * single access to the user. - * - * Accesses are clustered disregarding any app subattribution. - */ - private fun LightHistoricalPackageOps.clusterAccessesWithoutAttribution( - startTime: Long, - showSystem: Boolean - ): List<AppPermissionDiscreteAccessCluster> = - this.appPermissionDiscreteAccesses - .map { it.withLabel() } - .filterOutExemptAppPermissions(showSystem) - .filterAccessesLaterThan(startTime) - .flatMap { createAccessClusters(it) } - - /** Filters out accesses earlier than the provided start time. */ - private fun List<AppPermissionDiscreteAccessesWithLabel>.filterAccessesLaterThan( - startTime: Long, - ): List<AppPermissionDiscreteAccessesWithLabel> = - this.mapNotNull { - val updatedDiscreteAccesses = - it.discreteAccesses.filter { access -> access.accessTimeMs > startTime } - if (updatedDiscreteAccesses.isEmpty()) null - else - AppPermissionDiscreteAccessesWithLabel( - it.appPermissionId, - it.attributionLabel, - it.attributionTags, - updatedDiscreteAccesses - ) + fun updateShow7DaysToggle(show7Days: Boolean) { + if (show7Days != state[SHOULD_SHOW_7_DAYS_KEY]) { + state[SHOULD_SHOW_7_DAYS_KEY] = show7Days } - - /** Filters out data for apps and permissions that don't need to be displayed in the UI. */ - private fun List<AppPermissionDiscreteAccessesWithLabel>.filterOutExemptAppPermissions( - showSystem: Boolean - ): List<AppPermissionDiscreteAccessesWithLabel> { - val exemptedPackages = Utils.getExemptedPackages(roleManager) - return filter { !exemptedPackages.contains(it.appPermissionId.packageName) } - .filter { it.appPermissionId.permissionGroup == permissionGroup } - .filter { isPermissionRequestedByApp(it.appPermissionId) } - .filter { showSystem || !isAppPermissionSystem(it.appPermissionId) } + show7DaysFlow.compareAndSet(!show7Days, show7Days) } /** - * Converts the provided [AppPermissionDiscreteAccesses] to a - * [AppPermissionDiscreteAccessesWithLabel] by adding a label. + * Returns the label for the provided package name, by first searching the cache otherwise + * retrieving it from the app's [android.content.pm.ApplicationInfo]. */ - private fun AppPermissionDiscreteAccesses.withLabel(): AppPermissionDiscreteAccessesWithLabel = - AppPermissionDiscreteAccessesWithLabel( - this.appPermissionId, - Resources.ID_NULL, - attributionTags = emptyList(), - this.discreteAccesses - ) - - /** Groups tag-attributed accesses for the provided app and permission by attribution label. */ - private fun AttributedAppPermissionDiscreteAccesses.groupAccessesByLabel( - lightPackageInfo: LightPackageInfo? - ): List<AppPermissionDiscreteAccessesWithLabel> { - if (lightPackageInfo == null) return emptyList() - - val appPermissionId = this.appPermissionId - val labelsToDiscreteAccesses = mutableMapOf<Int, MutableList<DiscreteAccess>>() - val labelsToTags = mutableMapOf<Int, MutableList<String>>() - - val appPermissionDiscreteAccessWithLabels = - mutableListOf<AppPermissionDiscreteAccessesWithLabel>() - - for ((tag, discreteAccesses) in this.attributedDiscreteAccesses) { - val label: Int = - if (tag == NO_ATTRIBUTION_TAG) Resources.ID_NULL - else lightPackageInfo.attributionTagsToLabels[tag] ?: Resources.ID_NULL - - if (!labelsToDiscreteAccesses.containsKey(label)) { - labelsToDiscreteAccesses[label] = mutableListOf() - } - labelsToDiscreteAccesses[label]?.addAll(discreteAccesses) - - if (!labelsToTags.containsKey(label)) { - labelsToTags[label] = mutableListOf() - } - labelsToTags[label]?.add(tag) - } - - for ((label, discreteAccesses) in labelsToDiscreteAccesses.entries) { - val tags = labelsToTags[label]?.toList() ?: listOf() - - appPermissionDiscreteAccessWithLabels.add( - AppPermissionDiscreteAccessesWithLabel( - appPermissionId, - label, - tags, - discreteAccesses.sortedBy { -1 * it.accessTimeMs } - ) - ) + fun getPackageLabel(packageName: String, user: UserHandle): String { + if (packageLabelCache.containsKey(packageName)) { + return requireNotNull(packageLabelCache[packageName]) } - - return appPermissionDiscreteAccessWithLabels + val packageLabel = packageRepository.getPackageLabel(packageName, user) + packageLabelCache[packageName] = packageLabel + return packageLabel } /** - * Clusters [DiscreteAccess]es represented by a [AppPermissionDiscreteAccessesWithLabel] into - * smaller groups to form a list of [AppPermissionDiscreteAccessCluster] instances. - * - * [DiscreteAccess]es which have accesses sufficiently close together in time will be places in - * the same cluster. + * Returns the icon for the provided package name and user, by first searching the cache + * otherwise retrieving it from the app's [android.content.pm.ApplicationInfo]. */ - private fun createAccessClusters( - appPermAccesses: AppPermissionDiscreteAccessesWithLabel, - ): List<AppPermissionDiscreteAccessCluster> { - val clusters = mutableListOf<AppPermissionDiscreteAccessCluster>() - val currentDiscreteAccesses = mutableListOf<DiscreteAccess>() - // Iterate entries in asc order based on access timestamp. - for (index in appPermAccesses.discreteAccesses.size - 1 downTo 0) { - val discreteAccess = appPermAccesses.discreteAccesses[index] - if (currentDiscreteAccesses.isEmpty()) { - currentDiscreteAccesses.add(discreteAccess) - } else if (!canAccessBeAddedToCluster(discreteAccess, currentDiscreteAccesses)) { - clusters.add( - AppPermissionDiscreteAccessCluster( - appPermAccesses.appPermissionId, - appPermAccesses.attributionLabel, - appPermAccesses.attributionTags, - currentDiscreteAccesses.toMutableList(), - if (isOpClusteredByItself(discreteAccess.opName)) discreteAccess.opName - else null - ) - ) - currentDiscreteAccesses.clear() - currentDiscreteAccesses.add(discreteAccess) - } else { - currentDiscreteAccesses.add(discreteAccess) - } + fun getBadgedPackageIcon(packageName: String, userHandle: UserHandle): Drawable? { + val packageNameWithUser: Pair<String, UserHandle> = Pair(packageName, userHandle) + if (packageIconCache.containsKey(packageNameWithUser)) { + return requireNotNull(packageIconCache[packageNameWithUser]) } - - if (currentDiscreteAccesses.isNotEmpty()) { - val opName = currentDiscreteAccesses.last().opName - clusters.add( - AppPermissionDiscreteAccessCluster( - appPermAccesses.appPermissionId, - appPermAccesses.attributionLabel, - appPermAccesses.attributionTags, - currentDiscreteAccesses.toMutableList(), - if (isOpClusteredByItself(opName)) opName else null - ) - ) + val packageIcon = packageRepository.getBadgedPackageIcon(packageName, userHandle) + if (packageIcon != null) { + packageIconCache[packageNameWithUser] = packageIcon } - return clusters - } - /** - * Returns whether the provided [DiscreteAccess] occurred close enough to those in the clustered - * list that it can be added to the cluster. - */ - private fun canAccessBeAddedToCluster( - currentAccess: DiscreteAccess, - clusteredAccesses: List<DiscreteAccess> - ): Boolean { - val clusterOp = clusteredAccesses.last().opName - if ( - (isOpClusteredByItself(currentAccess.opName) || isOpClusteredByItself(clusterOp)) && - currentAccess.opName != clusteredAccesses.last().opName - ) { - return false - } - val currentAccessMinute = currentAccess.accessTimeMs / ONE_MINUTE_MS - val prevMostRecentAccessMillis = - clusteredAccesses.maxOf { discreteAccess -> - if (discreteAccess.accessDurationMs > 0) - discreteAccess.accessTimeMs + discreteAccess.accessDurationMs - ONE_MINUTE_MS - else discreteAccess.accessTimeMs - } - val prevMostRecentAccessMinute = prevMostRecentAccessMillis / ONE_MINUTE_MS - return (currentAccessMinute - prevMostRecentAccessMinute) <= CLUSTER_SPACING_MINUTES + return packageIcon } - /** - * Determine if an op should be in its own cluster and hence display as an individual entry in - * the privacy timeline - */ - private fun isOpClusteredByItself(opName: String): Boolean { - if (isLocationByPassEnabled()) { - return opName == AppOpsManager.OPSTR_EMERGENCY_LOCATION + private fun getDurationSummary(durationMs: Long): String? { + // Only show the duration summary if it is at least (CLUSTER_SPACING_MINUTES + 1) minutes. + // Displaying a time that is shorter than the cluster granularity + // (CLUSTER_SPACING_MINUTES) will not convey useful information. + if (durationMs >= TimeUnit.MINUTES.toMillis(CLUSTER_SPACING_MINUTES + 1)) { + return getDurationUsedStr(application, durationMs) } - return false + return null } - /** - * Composes all UI information from a [AppPermissionDiscreteAccessCluster] into a - * [AppPermissionAccessUiInfo]. - */ - private fun AppPermissionDiscreteAccessCluster.buildAppPermissionAccessUiInfo(): - AppPermissionAccessUiInfo { - val context = application - // The end minute is exclusive here in terms of access, i.e. [1..5) as the private data - // was not accessed at minute 5, it helps calculate the duration correctly. - val accessEndTimeMillis = - discreteAccesses.maxOf { appOpEvent -> - if (appOpEvent.accessDurationMs > 0) - appOpEvent.accessTimeMs + appOpEvent.accessDurationMs - else appOpEvent.accessTimeMs + ONE_MINUTE_MS - } - val accessStartTimeMillis = discreteAccesses.minOf { it.accessTimeMs } - val durationMs = accessEndTimeMillis - accessStartTimeMillis - val durationSummaryLabel = - if (durationMs >= TimeUnit.MINUTES.toMillis(CLUSTER_SPACING_MINUTES + 1)) { - getDurationUsedStr(context, durationMs) - } else null - - val proxyLabel = getProxyPackageLabel(this) - val subAttributionLabel = getSubAttributionLabel(this) - val showingSubAttribution = !subAttributionLabel.isNullOrEmpty() - val summary = - buildUsageSummary(context, subAttributionLabel, proxyLabel, durationSummaryLabel) - val isEmergencyLocationAccess = - isLocationByPassEnabled() && clusteredOp == AppOpsManager.OPSTR_EMERGENCY_LOCATION - - return AppPermissionAccessUiInfo( - this.appPermissionId.userHandle, - this.appPermissionId.packageName, - getPackageLabel(this.appPermissionId.packageName, this.appPermissionId.userHandle), - permissionGroup, - accessStartTimeMillis, - // Make the end time inclusive i.e. [1..4] - accessEndTimeMillis - ONE_MINUTE_MS, - summary, - showingSubAttribution, - this.attributionTags.toSet(), - getBadgedPackageIcon(this.appPermissionId.packageName, this.appPermissionId.userHandle), - isEmergencyLocationAccess - ) - } - - /** Builds a summary of the permission access. */ private fun buildUsageSummary( - context: Context, subAttributionLabel: String?, proxyPackageLabel: String?, - durationSummary: String? + durationSummary: String?, ): String? { val subTextStrings: MutableList<String> = mutableListOf() - subAttributionLabel?.let { subTextStrings.add(subAttributionLabel) } proxyPackageLabel?.let { subTextStrings.add(it) } durationSummary?.let { subTextStrings.add(it) } return when (subTextStrings.size) { 3 -> - context.getString( + application.getString( R.string.history_preference_subtext_3, subTextStrings[0], subTextStrings[1], - subTextStrings[2] + subTextStrings[2], ) 2 -> - context.getString( + application.getString( R.string.history_preference_subtext_2, subTextStrings[0], - subTextStrings[1] + subTextStrings[1], ) 1 -> subTextStrings[0] else -> null } } - /** Returns whether app subattribution should be shown. */ - private fun shouldShowSubAttributionForApp(lightPackageInfo: LightPackageInfo?): Boolean { - return lightPackageInfo != null && - shouldShowSubattributionInPermissionsDashboard() && - SubattributionUtils.isSubattributionSupported(lightPackageInfo) - } - - /** Returns the proxied package label if the permission access was proxied. */ - private fun getProxyPackageLabel(accessCluster: AppPermissionDiscreteAccessCluster): String? = - accessCluster.discreteAccesses - .firstOrNull { it.proxy?.packageName != null } - ?.let { - getPackageLabel( - it.proxy!!.packageName!!, - UserHandle.getUserHandleForUid(it.proxy.uid) - ) - } - - /** Returns the attribution label for the permission access, if any. */ - private fun getSubAttributionLabel(accessCluster: AppPermissionDiscreteAccessCluster): String? { - // Special case for EMERGENCY_LOCATION app op. Show enforced attribution label in the - // Privacy Dashboard - if ( - isLocationByPassEnabled() && - accessCluster.clusteredOp == AppOpsManager.OPSTR_EMERGENCY_LOCATION - ) { - return application.getString( - R.string.privacy_dashboard_emergency_location_enforced_attribution_label - ) - } - - return if (accessCluster.attributionLabel == Resources.ID_NULL) null - else { - val lightPackageInfo = getLightPackageInfo(accessCluster.appPermissionId) - getSubAttributionLabels(lightPackageInfo)?.get(accessCluster.attributionLabel) - } - } - - private fun getSubAttributionLabels(lightPackageInfo: LightPackageInfo?): Map<Int, String>? = - if (lightPackageInfo == null) null - else SubattributionUtils.getAttributionLabels(application, lightPackageInfo) - - private fun getLightPackageInfo(appPermissionId: AppPermissionId) = - lightPackageInfoLiveDataMap[Pair(appPermissionId.packageName, appPermissionId.userHandle)] - ?.value - - private fun getLightPackageInfo(packageName: String, userHandle: UserHandle) = - lightPackageInfoLiveDataMap[Pair(packageName, userHandle)]?.value - - private fun AllLightHistoricalPackageOpsLiveData.getLightHistoricalPackageOps() = - this.value?.values - - /** Data used to create a preference for an app's permission usage. */ - data class AppPermissionAccessUiInfo( - val userHandle: UserHandle, - val packageName: String, - val packageLabel: String, - val permissionGroup: String, - val accessStartTime: Long, - val accessEndTime: Long, - val summaryText: CharSequence?, - val showingAttribution: Boolean, - val attributionTags: Set<String>, - val badgedPackageIcon: Drawable?, - val isEmergencyLocationAccess: Boolean - ) - - sealed class PermissionUsageDetailsUiState { - data object Loading : PermissionUsageDetailsUiState() - - data class Success( - val appPermissionAccessUiInfoList: List<AppPermissionAccessUiInfo>, - val containsSystemAppUsage: Boolean, - val showSystem: Boolean, - val show7Days: Boolean, - ) : PermissionUsageDetailsUiState() - } - - /** - * Data class representing a cluster of permission accesses close enough together to be - * displayed as a single access in the UI. - */ - private data class AppPermissionDiscreteAccessCluster( - val appPermissionId: AppPermissionId, - val attributionLabel: Int, - val attributionTags: List<String>, - val discreteAccesses: List<DiscreteAccess>, - val clusteredOp: String? - ) - - /** - * Data class representing all permission accesses for a particular package, user, permission - * and attribution label. - */ - private data class AppPermissionDiscreteAccessesWithLabel( - val appPermissionId: AppPermissionId, - val attributionLabel: Int, - val attributionTags: List<String>, - val discreteAccesses: List<DiscreteAccess> - ) - - /** [LiveData] object for [PermissionUsageDetailsUiState]. */ - private val _permissionUsagesDetailsInfoUiLiveData = - object : - SmartUpdateMediatorLiveData<@JvmSuppressWildcards PermissionUsageDetailsUiState>() { - private val getAppPermGroupUiInfoLiveData = { appPermissionId: AppPermissionId -> - AppPermGroupUiInfoLiveData[ - Triple( - appPermissionId.packageName, - appPermissionId.permissionGroup, - appPermissionId.userHandle, - )] - } - private val getLightPackageInfoLiveData = - { packageWithUserHandle: Pair<String, UserHandle> -> - LightPackageInfoLiveData[packageWithUserHandle] - } - - init { - addSource(allLightHistoricalPackageOpsLiveData) { update() } - addSource(showSystemLiveData) { update() } - addSource(show7DaysLiveData) { update() } - } - - override fun onUpdate() { - if (!allLightHistoricalPackageOpsLiveData.isInitialized) { - return - } - - val appPermissionIds = mutableSetOf<AppPermissionId>() - val allPackages: Set<Pair<String, UserHandle>> = - allLightHistoricalPackageOpsLiveData.value?.keys ?: setOf() - for (packageWithUserHandle: Pair<String, UserHandle> in allPackages) { - val appPermGroupIds = - allLightHistoricalPackageOpsLiveData.value - ?.get(packageWithUserHandle) - ?.appPermissionDiscreteAccesses - ?.map { it.appPermissionId } - ?.toSet() ?: setOf() - - appPermissionIds.addAll(appPermGroupIds) - } - - setSourcesToDifference( - appPermissionIds, - appPermGroupUiInfoLiveDataList, - getAppPermGroupUiInfoLiveData - ) { - update() - } - setSourcesToDifference( - allPackages, - lightPackageInfoLiveDataMap, - getLightPackageInfoLiveData - ) { - update() - } - - if (appPermGroupUiInfoLiveDataList.any { it.value.isStale }) { - return - } - - if (lightPackageInfoLiveDataMap.any { it.value.isStale }) { - return - } - - value = buildPermissionUsageDetailsUiInfo() - } - } - - override fun getPermissionUsagesDetailsInfoUiLiveData(): - LiveData<PermissionUsageDetailsUiState> = _permissionUsagesDetailsInfoUiLiveData - - override fun getShowSystem(): Boolean = showSystemLiveData.value ?: false - - override fun getShow7Days(): Boolean = show7DaysLiveData.value ?: false - /** Companion object for [PermissionUsageDetailsViewModel]. */ companion object { - const val ONE_HOUR_MS = 3_600_000 const val ONE_MINUTE_MS = 60_000 const val CLUSTER_SPACING_MINUTES: Long = 1L - private const val TELECOM_PACKAGE = "com.android.server.telecom" val TIME_7_DAYS_DURATION: Long = DAYS.toMillis(7) val TIME_24_HOURS_DURATION: Long = DAYS.toMillis(1) internal const val SHOULD_SHOW_SYSTEM_KEY = "showSystem" @@ -694,7 +305,7 @@ class PermissionUsageDetailsViewModel( listOf( Manifest.permission_group.CAMERA, Manifest.permission_group.LOCATION, - Manifest.permission_group.MICROPHONE + Manifest.permission_group.MICROPHONE, ) .flatMap { group -> PermissionMapping.getPlatformPermissionNamesOfGroup(group) } .mapNotNull { permName -> AppOpsManager.permissionToOp(permName) } @@ -719,7 +330,7 @@ class PermissionUsageDetailsViewModel( accessStartTime: Long, accessEndTime: Long, showingAttribution: Boolean, - attributionTags: Set<String> + attributionTags: Set<String>, ): Intent { return getManagePermissionUsageIntent( context, @@ -728,7 +339,7 @@ class PermissionUsageDetailsViewModel( accessStartTime, accessEndTime, showingAttribution, - attributionTags + attributionTags, ) ?: getDefaultManageAppPermissionsIntent(packageName, userHandle) } @@ -736,6 +347,7 @@ class PermissionUsageDetailsViewModel( * Gets an [Intent.ACTION_MANAGE_PERMISSION_USAGE] intent, or null if attribution shouldn't * be shown or the intent can't be handled. */ + @Suppress("DEPRECATION") private fun getManagePermissionUsageIntent( context: Context, packageName: String, @@ -743,7 +355,7 @@ class PermissionUsageDetailsViewModel( accessStartTime: Long, accessEndTime: Long, showingAttribution: Boolean, - attributionTags: Set<String> + attributionTags: Set<String>, ): Intent? { if ( !showingAttribution || @@ -768,13 +380,13 @@ class PermissionUsageDetailsViewModel( val resolveInfo = context.packageManager.resolveActivity( intent, - PackageManager.ResolveInfoFlags.of(0) + PackageManager.ResolveInfoFlags.of(0), ) if ( resolveInfo?.activityInfo == null || !Objects.equals( resolveInfo.activityInfo.permission, - Manifest.permission.START_VIEW_PERMISSION_USAGE + Manifest.permission.START_VIEW_PERMISSION_USAGE, ) ) { return null @@ -785,8 +397,9 @@ class PermissionUsageDetailsViewModel( private fun getDefaultManageAppPermissionsIntent( packageName: String, - userHandle: UserHandle + userHandle: UserHandle, ): Intent { + @Suppress("DEPRECATION") return Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS).apply { putExtra(Intent.EXTRA_USER, userHandle) putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) @@ -795,29 +408,65 @@ class PermissionUsageDetailsViewModel( private fun isLocationByPassEnabled(): Boolean = SdkLevel.isAtLeastV() && Flags.locationBypassPrivacyDashboardEnabled() + + fun create( + app: Application, + handle: SavedStateHandle, + permissionGroup: String, + ): PermissionUsageDetailsViewModel { + val permissionRepository = PermissionRepository.getInstance(app) + val packageRepository = PackageRepository.getInstance(app) + val appOpRepository = AppOpRepository.getInstance(app, permissionRepository) + val roleRepository = RoleRepository.getInstance(app) + val userRepository = UserRepository.getInstance(app) + val useCase = + GetPermissionGroupUsageDetailsUseCase( + permissionGroup, + packageRepository, + permissionRepository, + appOpRepository, + roleRepository, + userRepository, + ) + return PermissionUsageDetailsViewModel(app, useCase, handle, permissionGroup) + } + } + + /** Data used to create a preference for an app's permission usage. */ + data class AppPermissionAccessUiInfo( + val userHandle: UserHandle, + val packageName: String, + val packageLabel: String, + val permissionGroup: String, + val accessStartTime: Long, + val accessEndTime: Long, + val summaryText: CharSequence?, + val showingAttribution: Boolean, + val attributionTags: Set<String>, + val badgedPackageIcon: Drawable?, + val isEmergencyLocationAccess: Boolean, + ) + + sealed class PermissionUsageDetailsUiState { + data object Loading : PermissionUsageDetailsUiState() + + data class Success( + val appPermissionAccessUiInfoList: List<AppPermissionAccessUiInfo>, + val containsSystemAppUsage: Boolean, + val showSystem: Boolean, + val show7Days: Boolean, + ) : PermissionUsageDetailsUiState() } /** Factory for [PermissionUsageDetailsViewModel]. */ @RequiresApi(Build.VERSION_CODES.S) class PermissionUsageDetailsViewModelFactory( val app: Application, - owner: SavedStateRegistryOwner, private val permissionGroup: String, - ) : AbstractSavedStateViewModelFactory(owner, Bundle()) { - override fun <T : ViewModel> create( - key: String, - modelClass: Class<T>, - handle: SavedStateHandle, - ): T { + ) : ViewModelProvider.Factory { + override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { @Suppress("UNCHECKED_CAST") - return if ( - com.android.permission.flags.Flags.livedataRefactorPermissionTimelineEnabled() - ) { - Log.d("PermissionTimeline", "timeline refactor flag enabled..") - PermissionUsageDetailsViewModelV2.create(app, handle, permissionGroup) as T - } else { - PermissionUsageDetailsViewModel(app, handle, permissionGroup) as T - } + return create(app, extras.createSavedStateHandle(), permissionGroup) as T } } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelV2.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelV2.kt deleted file mode 100644 index 312a7ee20..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/model/v31/PermissionUsageDetailsViewModelV2.kt +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.permissioncontroller.permission.ui.model.v31 - -import android.app.AppOpsManager.OPSTR_EMERGENCY_LOCATION -import android.app.Application -import android.graphics.drawable.Drawable -import android.os.UserHandle -import androidx.annotation.VisibleForTesting -import androidx.lifecycle.LiveData -import androidx.lifecycle.SavedStateHandle -import androidx.lifecycle.asLiveData -import androidx.lifecycle.viewModelScope -import com.android.permissioncontroller.DeviceUtils -import com.android.permissioncontroller.R -import com.android.permissioncontroller.appops.data.repository.v31.AppOpRepository -import com.android.permissioncontroller.permission.data.repository.v31.PermissionRepository -import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModel -import com.android.permissioncontroller.permission.domain.model.v31.PermissionTimelineUsageModelWrapper -import com.android.permissioncontroller.permission.domain.usecase.v31.GetPermissionGroupUsageDetailsUseCase -import com.android.permissioncontroller.permission.domain.usecase.v31.isLocationByPassEnabled -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.SHOULD_SHOW_7_DAYS_KEY -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.SHOULD_SHOW_SYSTEM_KEY -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.TIME_24_HOURS_DURATION -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.Companion.TIME_7_DAYS_DURATION -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState -import com.android.permissioncontroller.pm.data.repository.v31.PackageRepository -import com.android.permissioncontroller.role.data.repository.v31.RoleRepository -import com.android.permissioncontroller.user.data.repository.v31.UserRepository -import java.time.Instant -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.stateIn - -class PermissionUsageDetailsViewModelV2( - app: Application, - private val getPermissionUsageDetailsUseCase: GetPermissionGroupUsageDetailsUseCase, - private val state: SavedStateHandle, - private val permissionGroup: String, - scope: CoroutineScope? = null, - private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default, - private val packageRepository: PackageRepository = PackageRepository.getInstance(app) -) : BasePermissionUsageDetailsViewModel(app) { - private val coroutineScope = scope ?: viewModelScope - private val context = app - - private val showSystemFlow = MutableStateFlow(state[SHOULD_SHOW_SYSTEM_KEY] ?: false) - private val show7DaysFlow = MutableStateFlow(state[SHOULD_SHOW_7_DAYS_KEY] ?: false) - - private val permissionTimelineUsagesFlow: - StateFlow<PermissionTimelineUsageModelWrapper> by lazy { - getPermissionUsageDetailsUseCase(coroutineScope) - .flowOn(defaultDispatcher) - .stateIn( - coroutineScope, - SharingStarted.WhileSubscribed(5000), - PermissionTimelineUsageModelWrapper.Loading - ) - } - - @VisibleForTesting - val permissionUsageDetailsUiStateFlow: Flow<PermissionUsageDetailsUiState> by lazy { - combine(permissionTimelineUsagesFlow, showSystemFlow, show7DaysFlow) { - permissionTimelineUsages, - showSystem, - show7Days -> - permissionTimelineUsages.buildPermissionUsageDetailsUiInfo(showSystem, show7Days) - } - .flowOn(defaultDispatcher) - } - - override fun getPermissionUsagesDetailsInfoUiLiveData(): - LiveData<PermissionUsageDetailsUiState> { - return permissionUsageDetailsUiStateFlow.asLiveData( - context = coroutineScope.coroutineContext - ) - } - - private fun PermissionTimelineUsageModelWrapper.buildPermissionUsageDetailsUiInfo( - showSystem: Boolean, - show7Days: Boolean - ): PermissionUsageDetailsUiState { - if (this is PermissionTimelineUsageModelWrapper.Loading) { - return PermissionUsageDetailsUiState.Loading - } - val timelineUsageModels = - (this as PermissionTimelineUsageModelWrapper.Success).timelineUsageModels - val startTime = - (System.currentTimeMillis() - getUsageDuration(show7Days)).coerceAtLeast( - Instant.EPOCH.toEpochMilli() - ) - - val permissionTimelineUsageModels = - timelineUsageModels.filter { it.accessEndMillis > startTime } - val containsSystemUsages = permissionTimelineUsageModels.any { !it.isUserSensitive } - val result = - permissionTimelineUsageModels - .filter { showSystem || it.isUserSensitive } - .map { clusterOps -> - val durationSummaryLabel = - if (clusterOps.durationMillis > 0) { - getDurationSummary(clusterOps.durationMillis) - } else { - null - } - val proxyLabel = getProxyPackageLabel(clusterOps) - val isEmergencyLocationAccess = - isLocationByPassEnabled() && - clusterOps.opNames.any { it == OPSTR_EMERGENCY_LOCATION } - val subAttributionLabel = - if (isEmergencyLocationAccess) { - emergencyLocationAttributionLabel - } else { - clusterOps.attributionLabel - } - val showingSubAttribution = !subAttributionLabel.isNullOrEmpty() - val summary = - buildUsageSummary(subAttributionLabel, proxyLabel, durationSummaryLabel) - PermissionUsageDetailsViewModel.AppPermissionAccessUiInfo( - UserHandle.of(clusterOps.userId), - clusterOps.packageName, - getPackageLabel(clusterOps.packageName, UserHandle.of(clusterOps.userId)), - permissionGroup, - clusterOps.accessStartMillis, - clusterOps.accessEndMillis, - summary, - showingSubAttribution, - clusterOps.attributionTags ?: emptySet(), - getBadgedPackageIcon( - clusterOps.packageName, - UserHandle.of(clusterOps.userId) - ), - isEmergencyLocationAccess - ) - } - .sortedBy { -1 * it.accessStartTime } - return PermissionUsageDetailsUiState.Success( - result, - containsSystemUsages, - showSystem, - show7Days - ) - } - - private val emergencyLocationAttributionLabel: String by lazy { - context.getString(R.string.privacy_dashboard_emergency_location_enforced_attribution_label) - } - - override fun getShowSystem(): Boolean = showSystemFlow.value - - override val showSystemLiveData = - showSystemFlow.asLiveData(context = coroutineScope.coroutineContext) - - override fun getShow7Days(): Boolean = show7DaysFlow.value - - private fun getUsageDuration(show7Days: Boolean): Long { - return if (show7Days && DeviceUtils.isHandheld()) { - TIME_7_DAYS_DURATION - } else { - TIME_24_HOURS_DURATION - } - } - - private fun getProxyPackageLabel(accessCluster: PermissionTimelineUsageModel): String? = - accessCluster.proxyPackageName?.let { proxyPackageName -> - if (accessCluster.proxyUserId != null) { - getPackageLabel(proxyPackageName, UserHandle.of(accessCluster.proxyUserId)) - } else null - } - - override fun updateShowSystemAppsToggle(showSystem: Boolean) { - if (showSystem != state[SHOULD_SHOW_SYSTEM_KEY]) { - state[SHOULD_SHOW_SYSTEM_KEY] = showSystem - } - showSystemFlow.compareAndSet(!showSystem, showSystem) - } - - override fun updateShow7DaysToggle(show7Days: Boolean) { - if (show7Days != state[SHOULD_SHOW_7_DAYS_KEY]) { - state[SHOULD_SHOW_7_DAYS_KEY] = show7Days - } - show7DaysFlow.compareAndSet(!show7Days, show7Days) - } - - // TODO review these methods when old impl is removed, suspend function?? - override fun getPackageLabel(app: Application, packageName: String, user: UserHandle): String { - return packageRepository.getPackageLabel(packageName, user) - } - - override fun getBadgedPackageIcon( - app: Application, - packageName: String, - user: UserHandle - ): Drawable? { - return packageRepository.getBadgedPackageIcon(packageName, user) - } - - companion object { - fun create( - app: Application, - handle: SavedStateHandle, - permissionGroup: String - ): PermissionUsageDetailsViewModelV2 { - val permissionRepository = PermissionRepository.getInstance(app) - val packageRepository = PackageRepository.getInstance(app) - val appOpRepository = AppOpRepository.getInstance(app, permissionRepository) - val roleRepository = RoleRepository.getInstance(app) - val userRepository = UserRepository.getInstance(app) - val useCase = - GetPermissionGroupUsageDetailsUseCase( - permissionGroup, - packageRepository, - permissionRepository, - appOpRepository, - roleRepository, - userRepository - ) - return PermissionUsageDetailsViewModelV2(app, useCase, handle, permissionGroup) - } - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/LocationProviderDialogScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/LocationProviderDialogScreen.kt index ff3c2cbc1..54ed66f0c 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/LocationProviderDialogScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/LocationProviderDialogScreen.kt @@ -21,10 +21,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.wear.compose.material3.Dialog -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionScaffold import com.android.permissioncontroller.permission.ui.wear.model.LocationProviderInterceptDialogArgs +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionScaffold @Composable fun LocationProviderDialogScreen( @@ -32,7 +32,7 @@ fun LocationProviderDialogScreen( onDismissRequest: () -> Unit, args: LocationProviderInterceptDialogArgs?, ) { - Dialog(show = showDialog, onDismissRequest = onDismissRequest) { + Dialog(visible = showDialog, onDismissRequest = onDismissRequest) { args?.run { WearPermissionScaffold( showTimeText = false, diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt index 959dc9137..15d0fbe5f 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt @@ -58,8 +58,8 @@ import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogA import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModelFactory import com.android.permissioncontroller.permission.ui.wear.model.ConfirmDialogArgs -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme import com.android.settingslib.RestrictedLockUtils /** @@ -98,7 +98,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { userHandle: UserHandle?, caller: String?, sessionId: Long, - grantCategory: String? + grantCategory: String?, ): Bundle { val arguments = Bundle() arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName) @@ -118,7 +118,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val activity = requireActivity() val packageName = @@ -145,7 +145,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { packageName, permGroupName, user, - sessionId + sessionId, ) val viewModel = ViewModelProvider(this, factory).get(AppPermissionViewModel::class.java) confirmDialogViewModel = @@ -182,14 +182,14 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { this, this, param.request, - param.buttonClickAction + param.buttonClickAction, ) } else { showConfirmDialog( ChangeRequest.GRANT_ALL_FILE_ACCESS, R.string.special_file_access_dialog, -1, - false + false, ) } setResult(param.result, permGroupName) @@ -207,7 +207,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { this, this, ChangeRequest.GRANT_BOTH, - APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW + APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW, ) } else { viewModel.onDenyAnyWay(args.changeRequest, args.buttonPressed, args.oneTime) @@ -225,7 +225,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { this, this, args.changeRequest!!, - args.buttonClicked!! + args.buttonClicked!!, ) confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = false } @@ -250,7 +250,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { onConfirmDialogCancelButtonClick, onAdvancedConfirmDialogOkButtonClick, onAdvancedConfirmDialogCancelButtonClick, - onDisabledAllowButtonTap + onDisabledAllowButtonTap, ) } } @@ -261,14 +261,14 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { changeRequest: ChangeRequest, @StringRes messageId: Int, buttonPressed: Int, - oneTime: Boolean + oneTime: Boolean, ) { confirmDialogViewModel.confirmDialogArgs = ConfirmDialogArgs( messageId = messageId, changeRequest = changeRequest, buttonPressed = buttonPressed, - oneTime = oneTime + oneTime = oneTime, ) confirmDialogViewModel.showConfirmDialogLiveData.value = true } @@ -284,7 +284,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { Intent() .putExtra( ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED, - permGroupName + permGroupName, ) .putExtra(ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT, result) requireActivity().setResult(Activity.RESULT_OK, intent) @@ -298,7 +298,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.GRANT_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW, GRANTED_ALWAYS, - false + false, ) ButtonType.ALLOW_ALWAYS -> GrantedStateChangeParam( @@ -306,7 +306,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.GRANT_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS, GRANTED_ALWAYS, - true + true, ) ButtonType.ALLOW_FOREGROUND -> GrantedStateChangeParam( @@ -314,7 +314,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.GRANT_FOREGROUND_ONLY, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND, GRANTED_FOREGROUND_ONLY, - true + true, ) ButtonType.ASK -> GrantedStateChangeParam( @@ -322,7 +322,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.REVOKE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ASK_EVERY_TIME, DENIED, - false + false, ) ButtonType.DENY -> GrantedStateChangeParam( @@ -330,7 +330,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.REVOKE_BOTH, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY, DENIED_DO_NOT_ASK_AGAIN, - false + false, ) ButtonType.DENY_FOREGROUND -> GrantedStateChangeParam( @@ -338,7 +338,7 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment { ChangeRequest.REVOKE_FOREGROUND, APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY_FOREGROUND, DENIED_DO_NOT_ASK_AGAIN, - false + false, ) else -> throw RuntimeException("Wrong button type: $buttonType") } @@ -349,5 +349,5 @@ data class GrantedStateChangeParam( val request: ChangeRequest, val buttonClickAction: Int, val result: Int, - val requiresCustomStorageBehavior: Boolean + val requiresCustomStorageBehavior: Boolean, ) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt index 552876b7d..06d14cc14 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsFragment.kt @@ -48,7 +48,7 @@ import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissi import com.android.permissioncontroller.permission.ui.wear.model.WearAppPermissionUsagesViewModelFactory import com.android.permissioncontroller.permission.ui.wear.model.WearLocationProviderInterceptDialogViewModel import com.android.permissioncontroller.permission.ui.wear.model.WearLocationProviderInterceptDialogViewModelFactory -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme import java.time.Instant import java.util.concurrent.TimeUnit @@ -63,7 +63,7 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val packageName = arguments?.getString(Intent.EXTRA_PACKAGE_NAME) ?: "" val user = @@ -93,7 +93,7 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb val viewModel = ViewModelProvider( owner = this, - factory = AppPermissionGroupsViewModelFactory(packageName, user, sessionId) + factory = AppPermissionGroupsViewModelFactory(packageName, user, sessionId), )[AppPermissionGroupsViewModel::class.java] wearViewModel = @@ -103,13 +103,13 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb val revokeDialogViewModel = ViewModelProvider( owner = this, - factory = AppPermissionGroupsRevokeDialogViewModelFactory() + factory = AppPermissionGroupsRevokeDialogViewModelFactory(), )[AppPermissionGroupsRevokeDialogViewModel::class.java] val locationProviderInterceptDialogViewModel = ViewModelProvider( owner = this, - factory = WearLocationProviderInterceptDialogViewModelFactory() + factory = WearLocationProviderInterceptDialogViewModelFactory(), )[WearLocationProviderInterceptDialogViewModel::class.java] val context = requireContext() @@ -125,7 +125,7 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb maxOf( System.currentTimeMillis() - TimeUnit.DAYS.toMillis(aggregateDataFilterBeginDays), - Instant.EPOCH.toEpochMilli() + Instant.EPOCH.toEpochMilli(), ) permissionUsages.load( null, @@ -137,7 +137,7 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb false, false, this, - false + false, ) } helper = @@ -151,7 +151,7 @@ class WearAppPermissionGroupsFragment : Fragment(), PermissionsUsagesChangeCallb viewModel = viewModel, wearViewModel = wearViewModel, revokeDialogViewModel = revokeDialogViewModel, - locationProviderInterceptDialogViewModel = locationProviderInterceptDialogViewModel + locationProviderInterceptDialogViewModel = locationProviderInterceptDialogViewModel, ) return ComposeView(activity).apply { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt index 5919fad0d..e375910ae 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionGroupsScreen.kt @@ -25,15 +25,15 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionConfirmationDialog +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControl +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion @Composable fun WearAppPermissionGroupsScreen(helper: WearAppPermissionGroupsHelper) { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt index 8815e7905..588f5a4da 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt @@ -30,20 +30,20 @@ import com.android.permissioncontroller.permission.ui.model.AppPermissionViewMod import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonState import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonType import com.android.permissioncontroller.permission.ui.v33.AdvancedConfirmDialogArgs -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListFooter -import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip -import com.android.permissioncontroller.permission.ui.wear.elements.material2.toggleChipDisabledColors -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType -import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertConfirmIcon -import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertDismissIcon import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel import com.android.permissioncontroller.permission.ui.wear.model.ConfirmDialogArgs -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material2.ListFooter +import com.android.permissioncontroller.wear.permission.components.material2.ToggleChip +import com.android.permissioncontroller.wear.permission.components.material2.toggleChipDisabledColors +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionConfirmationDialog +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.material3.defaultAlertConfirmIcon +import com.android.permissioncontroller.wear.permission.components.material3.defaultAlertDismissIcon +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion import com.android.settingslib.RestrictedLockUtils @Composable diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt index e81fd948d..088531a52 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt @@ -27,7 +27,7 @@ import androidx.fragment.app.DialogFragment import androidx.fragment.app.viewModels import com.android.permissioncontroller.ecm.EnhancedConfirmationDialogActivity import com.android.permissioncontroller.permission.ui.wear.model.WearEnhancedConfirmationViewModel -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme class WearEnhancedConfirmationDialogFragment : DialogFragment() { private lateinit var enhancedConfirmationDialogActivity: EnhancedConfirmationDialogActivity @@ -42,7 +42,7 @@ class WearEnhancedConfirmationDialogFragment : DialogFragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View { val title = arguments?.getString(KEY_TITLE) ?: throw RuntimeException("ECM Title can't be null") diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt index ab19a9665..1e1f8ba5a 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt @@ -39,20 +39,20 @@ import androidx.wear.compose.material.CircularProgressIndicator import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.SwipeToDismissBox import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.CheckYourPhoneScreen -import com.android.permissioncontroller.permission.ui.wear.elements.CheckYourPhoneState -import com.android.permissioncontroller.permission.ui.wear.elements.CheckYourPhoneState.InProgress -import com.android.permissioncontroller.permission.ui.wear.elements.CheckYourPhoneState.Success -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.dismiss -import com.android.permissioncontroller.permission.ui.wear.elements.findActivity -import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.permission.ui.wear.model.WearEnhancedConfirmationViewModel import com.android.permissioncontroller.permission.ui.wear.model.WearEnhancedConfirmationViewModel.ScreenState -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.CheckYourPhoneScreen +import com.android.permissioncontroller.wear.permission.components.CheckYourPhoneState +import com.android.permissioncontroller.wear.permission.components.CheckYourPhoneState.InProgress +import com.android.permissioncontroller.wear.permission.components.CheckYourPhoneState.Success +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.dismiss +import com.android.permissioncontroller.wear.permission.components.findActivity +import com.android.permissioncontroller.wear.permission.components.material2.Chip +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionConfirmationDialog +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper @Composable fun WearEnhancedConfirmationScreen( diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt index 20c010781..3ed58cf4a 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearGrantPermissionsScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.stringResource +import androidx.core.util.size import androidx.wear.compose.material3.Dialog import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.ALLOW_ALWAYS_BUTTON @@ -38,13 +39,13 @@ import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.N import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_AND_DONT_ASK_AGAIN_BUTTON import com.android.permissioncontroller.permission.ui.GrantPermissionsActivity.NO_UPGRADE_OT_BUTTON import com.android.permissioncontroller.permission.ui.wear.GrantPermissionsWearViewHandler.BUTTON_RES_ID_TO_NUM -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType import com.android.permissioncontroller.permission.ui.wear.model.WearGrantPermissionsViewModel -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL3 +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControl +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion.MATERIAL3 @Composable fun WearGrantPermissionsScreen( @@ -84,7 +85,7 @@ fun WearGrantPermissionsScreen( ) } } - for (i in 0 until BUTTON_RES_ID_TO_NUM.size()) { + for (i in 0 until BUTTON_RES_ID_TO_NUM.size) { val pos: Int = BUTTON_RES_ID_TO_NUM.valueAt(i) if (buttonVisibilities.value.size <= pos) { // initial value of buttonVisibilities is empty @@ -135,7 +136,7 @@ private fun AsDialog( content: @Composable () -> Unit, ) { val showDialog = viewModel.showDialog.observeAsState(false) - Dialog(show = showDialog.value, onDismissRequest = onDismissRequest, content = content) + Dialog(visible = showDialog.value, onDismissRequest = onDismissRequest, content = content) } @Composable diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt index d826e501e..72c3d2054 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionScreen.kt @@ -25,9 +25,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.res.stringResource import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder @Composable fun WearManageCustomPermissionScreen( diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt index a9e83919f..96da37b9b 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageCustomPermissionsFragment.kt @@ -26,13 +26,13 @@ import androidx.lifecycle.ViewModelProvider import com.android.permissioncontroller.Constants import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment import com.android.permissioncontroller.permission.ui.model.ManageCustomPermissionsViewModel -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme class WearManageCustomPermissionsFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val activity = requireActivity() val application = activity.getApplication() @@ -41,14 +41,14 @@ class WearManageCustomPermissionsFragment : Fragment() { val viewModel = ViewModelProvider( this, - ViewModelProvider.AndroidViewModelFactory.getInstance(application) + ViewModelProvider.AndroidViewModelFactory.getInstance(application), ) .get(ManageCustomPermissionsViewModel::class.java) val onPermGroupClick: (String) -> Unit = { permGroupName -> viewModel.showPermissionApps( this, - PermissionAppsFragment.createArgs(permGroupName, sessionId) + PermissionAppsFragment.createArgs(permGroupName, sessionId), ) } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt index 3e347e19c..2fdf33130 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionScreen.kt @@ -29,13 +29,13 @@ import androidx.compose.ui.res.stringResource import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.model.livedatatypes.PermGroupPackagesUiInfo import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupIcon import com.android.permissioncontroller.permission.utils.KotlinUtils.getPermGroupLabel import com.android.permissioncontroller.permission.utils.StringUtils import com.android.permissioncontroller.permission.utils.Utils +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder import java.text.Collator @Composable diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt index 16ed1f067..d88554562 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearManageStandardPermissionsFragment.kt @@ -27,13 +27,13 @@ import com.android.permissioncontroller.Constants import com.android.permissioncontroller.permission.ui.handheld.ManageCustomPermissionsFragment import com.android.permissioncontroller.permission.ui.handheld.PermissionAppsFragment import com.android.permissioncontroller.permission.ui.model.ManageStandardPermissionsViewModel -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme class WearManageStandardPermissionsFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val activity = requireActivity() val application = activity.getApplication() @@ -42,20 +42,20 @@ class WearManageStandardPermissionsFragment : Fragment() { val viewModel: ManageStandardPermissionsViewModel = ViewModelProvider( this, - ViewModelProvider.AndroidViewModelFactory.getInstance(application) + ViewModelProvider.AndroidViewModelFactory.getInstance(application), ) .get(ManageStandardPermissionsViewModel::class.java) val onPermGroupClick: (String) -> Unit = { permGroupName -> viewModel.showPermissionApps( this, - PermissionAppsFragment.createArgs(permGroupName, sessionId) + PermissionAppsFragment.createArgs(permGroupName, sessionId), ) } val onCustomPermGroupClick = { viewModel.showCustomPermissions( this, - ManageCustomPermissionsFragment.createArgs(sessionId) + ManageCustomPermissionsFragment.createArgs(sessionId), ) } val onAutoRevokeClick = { @@ -69,7 +69,7 @@ class WearManageStandardPermissionsFragment : Fragment() { viewModel, onPermGroupClick, onCustomPermGroupClick, - onAutoRevokeClick + onAutoRevokeClick, ) } } 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 2fa6aa7f3..6f0d94d02 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionAppsScreen.kt @@ -30,10 +30,10 @@ import androidx.compose.ui.res.stringResource import androidx.wear.compose.material.Text import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.ui.Category -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListSubHeader +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionListSubHeader /** Compose the screen associated to a [WearPermissionAppsFragment]. */ @Composable diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsFragment.kt index 2ade4863a..2d302c2b4 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsFragment.kt @@ -29,7 +29,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity -import com.android.permissioncontroller.permission.ui.model.v31.BasePermissionUsageDetailsViewModel +import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsViewModelFactory /** @@ -42,7 +42,7 @@ class WearPermissionUsageDetailsFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val permissionGroup = arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME) @@ -56,11 +56,10 @@ class WearPermissionUsageDetailsFragment : Fragment() { val factory = PermissionUsageDetailsViewModelFactory( PermissionControllerApplication.get(), - this, - permissionGroup + permissionGroup, ) val viewModel = - ViewModelProvider(this, factory).get(BasePermissionUsageDetailsViewModel::class.java) + ViewModelProvider(this, factory).get(PermissionUsageDetailsViewModel::class.java) viewModel.updateShowSystemAppsToggle(showSystem) return ComposeView(requireContext()).apply { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsScreen.kt index 279eaa8cc..bea10483b 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageDetailsScreen.kt @@ -31,21 +31,20 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.model.v31.BasePermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.AppPermissionAccessUiInfo import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.permission.utils.KotlinUtils +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder @RequiresApi(Build.VERSION_CODES.S) @Composable fun WearPermissionUsageDetailsScreen( permissionGroup: String, - viewModel: BasePermissionUsageDetailsViewModel, + viewModel: PermissionUsageDetailsViewModel, ) { val context = LocalContext.current val uiData = viewModel.getPermissionUsagesDetailsInfoUiLiveData().observeAsState(null) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageScreen.kt index f8af241d7..8631d8b20 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearPermissionUsageScreen.kt @@ -33,10 +33,10 @@ import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.ui.handheld.v31.PermissionUsageControlPreference import com.android.permissioncontroller.permission.ui.viewmodel.v31.PermissionUsageViewModel import com.android.permissioncontroller.permission.ui.viewmodel.v31.PermissionUsagesUiState -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.permission.utils.Utils +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder import java.text.Collator @RequiresApi(Build.VERSION_CODES.S) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt index 64acfdd96..d454cc566 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsFragment.kt @@ -41,14 +41,14 @@ import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel. import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModelFactory import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel.UnusedAppChip -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme import com.android.permissioncontroller.permission.utils.KotlinUtils +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme import com.android.settingslib.utils.applications.AppUtils import java.text.Collator /** * This is a condensed version of - * [com.android.permissioncontroller.permission.ui.UnusedAppsFragment.kt], tailored for Wear. + * [com.android.permissioncontroller.permission.ui.UnusedAppsFragment], tailored for Wear. * * A fragment displaying all applications that are unused as well as the option to remove them and * to open them. @@ -62,7 +62,7 @@ class WearUnusedAppsFragment : Fragment() { private var sessionId: Long = 0L private var isFirstLoad = false private var categoryVisibilities: MutableList<Boolean> = - MutableList(UnusedPeriod.values().size) { false } + MutableList(UnusedPeriod.entries.size) { false } private var unusedAppsMap: MutableMap<UnusedPeriod, MutableMap<String, UnusedAppChip>> = initUnusedAppsMap() @@ -87,7 +87,7 @@ class WearUnusedAppsFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { isFirstLoad = true context = requireContext() @@ -101,7 +101,7 @@ class WearUnusedAppsFragment : Fragment() { wearViewModel = ViewModelProvider( this, - ViewModelProvider.AndroidViewModelFactory.getInstance(application) + ViewModelProvider.AndroidViewModelFactory.getInstance(application), ) .get(WearUnusedAppsViewModel::class.java) viewModel.unusedPackageCategoriesLiveData.observe( @@ -111,7 +111,7 @@ class WearUnusedAppsFragment : Fragment() { updatePackages(pkgs) updateWearViewModel(false) } - } + }, ) if (!viewModel.unusedPackageCategoriesLiveData.isInitialized) { @@ -125,7 +125,7 @@ class WearUnusedAppsFragment : Fragment() { updateWearViewModel(false) } }, - SHOW_LOAD_DELAY_MS + SHOW_LOAD_DELAY_MS, ) } else { updatePackages(viewModel.unusedPackageCategoriesLiveData.value!!) @@ -192,14 +192,14 @@ class WearUnusedAppsFragment : Fragment() { getString( R.string.auto_revoked_app_summary_two, importantLabel, - otherLabel + otherLabel, ) } else -> getString( R.string.auto_revoked_app_summary_many, importantLabel, - "${revokedPerms.size - 1}" + "${revokedPerms.size - 1}", ) } @@ -215,9 +215,9 @@ class WearUnusedAppsFragment : Fragment() { AppUtils.getAppContentDescription( context, pkgName, - user.getIdentifier() + user.getIdentifier(), ), - onChipClicked + onChipClicked, ) unusedAppsMap[period]!!.put(key, chip) } @@ -242,7 +242,7 @@ class WearUnusedAppsFragment : Fragment() { for (period in allPeriods) { Log.i( LOG_TAG, - "sessionId: $sessionId $period unused: " + "${categorizedPackages[period]}" + "sessionId: $sessionId $period unused: " + "${categorizedPackages[period]}", ) for (revokedPackageInfo in categorizedPackages[period]!!) { for (groupName in revokedPackageInfo.revokedGroups) { @@ -251,7 +251,7 @@ class WearUnusedAppsFragment : Fragment() { revokedPackageInfo.packageName, revokedPackageInfo.user, groupName, - isNewlyRevoked + isNewlyRevoked, ) } } @@ -292,7 +292,7 @@ class WearUnusedAppsFragment : Fragment() { private fun compareUnusedApps( lhs: Pair<String, UnusedAppChip>, - rhs: Pair<String, UnusedAppChip> + rhs: Pair<String, UnusedAppChip>, ): Int { var result = collator.compare(lhs.second.label, rhs.second.label) if (result == 0) { @@ -303,7 +303,7 @@ class WearUnusedAppsFragment : Fragment() { private fun updateWearViewModel(isLoading: Boolean) { wearViewModel.loadingLiveData.value = isLoading - wearViewModel.unusedPeriodCategoryVisibilitiesLiveData.setValue(categoryVisibilities) + wearViewModel.unusedPeriodCategoryVisibilitiesLiveData.value = categoryVisibilities // Need to copy to non mutable maps or compose will not update correctly val map = mutableMapOf<UnusedPeriod, Map<String, UnusedAppChip>>() @@ -311,6 +311,6 @@ class WearUnusedAppsFragment : Fragment() { map.put(period, unusedAppsMap[period]!!.toMap()) } - wearViewModel.unusedAppChipsLiveData.setValue(map.toMap()) + wearViewModel.unusedAppChipsLiveData.value = map.toMap() } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt index 0bde97f81..c5eef53f2 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUnusedAppsScreen.kt @@ -25,10 +25,10 @@ import com.android.permissioncontroller.R import com.android.permissioncontroller.hibernation.isHibernationEnabled import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod.Companion.allPeriods -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder @Composable fun WearUnusedAppsScreen(viewModel: WearUnusedAppsViewModel) { 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 7e4e939b9..6cdf47cec 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearUtils.kt @@ -22,7 +22,6 @@ 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) @@ -48,7 +47,7 @@ object WearUtils { res.getString( R.string.wear_app_perms_7d_access, summaryTimestamp.third, - summaryTimestamp.first + summaryTimestamp.first, ) else -> "" } @@ -57,7 +56,7 @@ object WearUtils { @JvmStatic private fun getPermissionLastAccessSummaryTimestamp( lastAccessTime: Long?, - context: Context + context: Context, ): Triple<String, Int, String> { val midnightToday = (ZonedDateTime.now().truncatedTo(ChronoUnit.DAYS).toEpochSecond() * 1000L) @@ -78,8 +77,4 @@ 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/RemoteConnectionProgressIndicator.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/RemoteConnectionProgressIndicator.kt deleted file mode 100644 index 244e7e3fd..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/RemoteConnectionProgressIndicator.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 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 - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.permissioncontroller.permission.ui.wear.elements - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import androidx.wear.compose.material.CircularProgressIndicator -import androidx.wear.compose.material.Icon -import androidx.wear.compose.material.MaterialTheme - -@Composable -fun RemoteConnectionProgressIndicator(iconRes: Int, modifier: Modifier) { - val indicatorPadding = 8.dp - val iconSize = 48.dp - val progressBarStrokeWidth = 4.dp - Box( - modifier = modifier.size(iconSize).clip(CircleShape), - ) { - CircularProgressIndicator( - modifier = Modifier.size(iconSize - progressBarStrokeWidth + indicatorPadding), - strokeWidth = progressBarStrokeWidth, - ) - Icon( - painter = painterResource(iconRes), - contentDescription = null, - modifier = - Modifier.align(Alignment.Center) - .size(iconSize - indicatorPadding - 8.dp) - .clip(CircleShape), - ) - } -} - -@Composable -fun RemoteConnectionSuccess(iconRes: Int, modifier: Modifier) { - val indicatorPadding = 8.dp - val iconSize = 48.dp - val backgroundColor = MaterialTheme.colors.onSurface - val contentColor = MaterialTheme.colors.surface - Box( - modifier = modifier.size(iconSize).clip(CircleShape).background(backgroundColor), - ) { - Icon( - painter = painterResource(iconRes), - contentDescription = null, - tint = contentColor, - modifier = - Modifier.align(Alignment.Center) - .size(iconSize - indicatorPadding - 8.dp) - .clip(CircleShape), - ) - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt deleted file mode 100644 index 736d543a3..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTheme.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.permissioncontroller.permission.ui.wear.theme - -import android.content.Context -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.annotation.StringRes -import androidx.annotation.VisibleForTesting -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.DeviceFontFamilyName -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.wear.compose.material.Colors -import androidx.wear.compose.material.MaterialTheme -import androidx.wear.compose.material.Typography -import androidx.wear.compose.material3.MaterialTheme as Material3Theme -import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL2_5 -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL3 - -/** This enum is used to specify the material version used for a specific screen */ -enum class WearPermissionMaterialUIVersion { - MATERIAL2_5, - MATERIAL3, -} - -/** - * Supports both Material 3 and Material 2_5 theme. default version for permission theme will be 2_5 - * until we migrate enough screens to 3. 2_5 version will use material 3 overlay resources if we - * enable material3 for even one screen (Permission screens will be migrated in phases). - */ -@Composable -fun WearPermissionTheme( - version: WearPermissionMaterialUIVersion = MATERIAL2_5, - content: @Composable () -> Unit, -) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { - WearPermissionLegacyTheme(content) - } else { - // Material3 UI controls are still being used in the screen that the theme is applied - if (version == MATERIAL3) { - val material3Theme = WearOverlayableMaterial3Theme(LocalContext.current) - Material3Theme( - colorScheme = material3Theme.colorScheme, - typography = material3Theme.typography, - shapes = material3Theme.shapes, - content = content, - ) - } - // Material2_5 UI controls are still being used in the screen that the theme is applied, - // But some in-app screens(like permission grant screen) are migrated to material3. - // To avoid having two set of overlay resources, we will use material3 overlay resources to - // support material2_5 UI controls as well. - else if (version == MATERIAL2_5 && ResourceHelper.materialUIVersionInApp == MATERIAL3) { - val material3Theme = WearOverlayableMaterial3Theme(LocalContext.current) - val bridgedLegacyTheme = WearMaterialBridgedLegacyTheme.createFrom(material3Theme) - MaterialTheme( - colors = bridgedLegacyTheme.colors, - typography = bridgedLegacyTheme.typography, - shapes = bridgedLegacyTheme.shapes, - content = content, - ) - } - // We are not ready for material3 yet in any screens. - else { - WearPermissionLegacyTheme(content) - } - } -} - -/** - * The Material 2.5 Theme Wrapper for Supporting RRO with legacy resources. This theme is kept here - * for backward compatibility. When grant screen is updated to material3 will clean up legacy - * resources. - */ -@Composable -fun WearPermissionLegacyTheme(content: @Composable () -> Unit) { - val context = LocalContext.current - val colors = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - overlayColors(context) - .copy(error = MaterialTheme.colors.error, onError = MaterialTheme.colors.onError) - } else { - MaterialTheme.colors - } - MaterialTheme(colors = colors, typography = deviceDefaultTypography(context), content = content) -} - -/** - * Creates a dynamic color maps that can be overlaid. 100 - Lightest shade; 0 - Darkest Shade; In - * wear we only support dark theme for the time being. Thus the fill colors and variants are dark - * and anything on top is light. We will use this custom redirection until wear compose material - * supports color scheming. - * - * The mapping is best case match on wear material color tokens from - * /android/clockwork/common/wearable/wearmaterial/color/res/values/color-tokens.xml - * - * @param context The context required to get system resource data. - */ -@RequiresApi(Build.VERSION_CODES.S) -@VisibleForTesting -internal fun overlayColors(context: Context): Colors { - val tonalPalette = dynamicTonalPalette(context) - return Colors( - background = Color.Black, - onBackground = Color.White, - primary = tonalPalette.primary90, - primaryVariant = tonalPalette.primary80, - onPrimary = tonalPalette.primary10, - secondary = tonalPalette.tertiary90, - secondaryVariant = tonalPalette.tertiary60, - onSecondary = tonalPalette.tertiary10, - surface = tonalPalette.neutral20, - onSurface = tonalPalette.neutral95, - onSurfaceVariant = tonalPalette.neutralVariant80, - ) -} - -private fun fontFamily(context: Context, @StringRes id: Int): FontFamily { - val typefaceName = context.resources.getString(id) - val font = Font(familyName = DeviceFontFamilyName(typefaceName)) - return FontFamily(font) -} - -/* - Only customizes font family. The material 3 roles to 2.5 are mapped to the best case matching of - google3/java/com/google/android/wearable/libraries/compose/theme/GoogleMaterialTheme.kt -*/ -internal fun deviceDefaultTypography(context: Context): Typography { - val defaultTypography = Typography() - return Typography( - display1 = - defaultTypography.display1.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_display_1_font_family) - ), - display2 = - defaultTypography.display2.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_display_2_font_family) - ), - display3 = - defaultTypography.display3.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_display_3_font_family) - ), - title1 = - defaultTypography.title1.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_title_1_font_family) - ), - title2 = - defaultTypography.title2.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_title_2_font_family) - ), - title3 = - defaultTypography.title3.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_title_3_font_family) - ), - body1 = - defaultTypography.body1.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_body_1_font_family) - ), - body2 = - defaultTypography.body2.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_body_2_font_family) - ), - button = - defaultTypography.button.copy( - fontFamily = fontFamily(context, R.string.wear_material_compose_button_font_family) - ), - caption1 = - defaultTypography.caption1.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_caption_1_font_family) - ), - caption2 = - defaultTypography.caption2.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_caption_2_font_family) - ), - caption3 = - defaultTypography.caption3.copy( - fontFamily = - fontFamily(context, R.string.wear_material_compose_caption_3_font_family) - ), - ) -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTonalPalette.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTonalPalette.kt deleted file mode 100644 index a86af8b3d..000000000 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearPermissionTonalPalette.kt +++ /dev/null @@ -1,191 +0,0 @@ -@file:Suppress("unused") - -package com.android.permissioncontroller.permission.ui.wear.theme - -import android.R -import android.content.Context -import android.os.Build -import androidx.annotation.ColorRes -import androidx.annotation.DoNotInline -import androidx.annotation.RequiresApi -import androidx.compose.ui.graphics.Color - -/** - * Tonal Palette structure in Material. - * - * A tonal palette is comprised of 5 tonal ranges. Each tonal range includes the 13 stops, or tonal - * swatches. - * - * Tonal range names are: - * - Neutral (N) - * - Neutral variant (NV) - * - Primary (P) - * - Secondary (S) - * - Tertiary (T) - */ -internal class WearPermissionTonalPalette( - // The neutral tonal range. - val neutral100: Color, - val neutral99: Color, - val neutral95: Color, - val neutral90: Color, - val neutral80: Color, - val neutral70: Color, - val neutral60: Color, - val neutral50: Color, - val neutral40: Color, - val neutral30: Color, - val neutral20: Color, - val neutral10: Color, - val neutral0: Color, - - // The neutral variant tonal range, sometimes called "neutral 2" - val neutralVariant100: Color, - val neutralVariant99: Color, - val neutralVariant95: Color, - val neutralVariant90: Color, - val neutralVariant80: Color, - val neutralVariant70: Color, - val neutralVariant60: Color, - val neutralVariant50: Color, - val neutralVariant40: Color, - val neutralVariant30: Color, - val neutralVariant20: Color, - val neutralVariant10: Color, - val neutralVariant0: Color, - - // The primary tonal range, also known as accent 1 - val primary100: Color, - val primary99: Color, - val primary95: Color, - val primary90: Color, - val primary80: Color, - val primary70: Color, - val primary60: Color, - val primary50: Color, - val primary40: Color, - val primary30: Color, - val primary20: Color, - val primary10: Color, - val primary0: Color, - - // The Secondary tonal range, also know as accent 2 - val secondary100: Color, - val secondary99: Color, - val secondary95: Color, - val secondary90: Color, - val secondary80: Color, - val secondary70: Color, - val secondary60: Color, - val secondary50: Color, - val secondary40: Color, - val secondary30: Color, - val secondary20: Color, - val secondary10: Color, - val secondary0: Color, - - // The tertiary tonal range, also known as accent 3 - val tertiary100: Color, - val tertiary99: Color, - val tertiary95: Color, - val tertiary90: Color, - val tertiary80: Color, - val tertiary70: Color, - val tertiary60: Color, - val tertiary50: Color, - val tertiary40: Color, - val tertiary30: Color, - val tertiary20: Color, - val tertiary10: Color, - val tertiary0: Color, -) -/** Dynamic colors for wear compose material to support resource overlay. */ -@RequiresApi(Build.VERSION_CODES.S) -// TODO: once we have proper support for this on Wear 6+, we will do something similar to -// https://source.corp.google.com/h/android/platform/superproject/+/androidx-main:frameworks/support/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.android.kt;l=307-362?q=dynamicTonalPalette&sq=repo:android%2Fplatform%2Fsuperproject%20b:androidx-main -// Tracking Bug: b/270720571 -internal fun dynamicTonalPalette(context: Context) = - WearPermissionTonalPalette( - // The neutral tonal range from the generated dynamic color palette. - neutral100 = ColorResourceHelper.getColor(context, R.color.system_neutral1_0), - neutral99 = ColorResourceHelper.getColor(context, R.color.system_neutral1_10), - neutral95 = ColorResourceHelper.getColor(context, R.color.system_neutral1_50), - neutral90 = ColorResourceHelper.getColor(context, R.color.system_neutral1_100), - neutral80 = ColorResourceHelper.getColor(context, R.color.system_neutral1_200), - neutral70 = ColorResourceHelper.getColor(context, R.color.system_neutral1_300), - neutral60 = ColorResourceHelper.getColor(context, R.color.system_neutral1_400), - neutral50 = ColorResourceHelper.getColor(context, R.color.system_neutral1_500), - neutral40 = ColorResourceHelper.getColor(context, R.color.system_neutral1_600), - neutral30 = ColorResourceHelper.getColor(context, R.color.system_neutral1_700), - neutral20 = ColorResourceHelper.getColor(context, R.color.system_neutral1_800), - neutral10 = ColorResourceHelper.getColor(context, R.color.system_neutral1_900), - neutral0 = ColorResourceHelper.getColor(context, R.color.system_neutral1_1000), - - // The neutral variant tonal range, sometimes called "neutral 2", from the - // generated dynamic color palette. - neutralVariant100 = ColorResourceHelper.getColor(context, R.color.system_neutral2_0), - neutralVariant99 = ColorResourceHelper.getColor(context, R.color.system_neutral2_10), - neutralVariant95 = ColorResourceHelper.getColor(context, R.color.system_neutral2_50), - neutralVariant90 = ColorResourceHelper.getColor(context, R.color.system_neutral2_100), - neutralVariant80 = ColorResourceHelper.getColor(context, R.color.system_neutral2_200), - neutralVariant70 = ColorResourceHelper.getColor(context, R.color.system_neutral2_300), - neutralVariant60 = ColorResourceHelper.getColor(context, R.color.system_neutral2_400), - neutralVariant50 = ColorResourceHelper.getColor(context, R.color.system_neutral2_500), - neutralVariant40 = ColorResourceHelper.getColor(context, R.color.system_neutral2_600), - neutralVariant30 = ColorResourceHelper.getColor(context, R.color.system_neutral2_700), - neutralVariant20 = ColorResourceHelper.getColor(context, R.color.system_neutral2_800), - neutralVariant10 = ColorResourceHelper.getColor(context, R.color.system_neutral2_900), - neutralVariant0 = ColorResourceHelper.getColor(context, R.color.system_neutral2_1000), - - // The primary tonal range from the generated dynamic color palette. - primary100 = ColorResourceHelper.getColor(context, R.color.system_accent1_0), - primary99 = ColorResourceHelper.getColor(context, R.color.system_accent1_10), - primary95 = ColorResourceHelper.getColor(context, R.color.system_accent1_50), - primary90 = ColorResourceHelper.getColor(context, R.color.system_accent1_100), - primary80 = ColorResourceHelper.getColor(context, R.color.system_accent1_200), - primary70 = ColorResourceHelper.getColor(context, R.color.system_accent1_300), - primary60 = ColorResourceHelper.getColor(context, R.color.system_accent1_400), - primary50 = ColorResourceHelper.getColor(context, R.color.system_accent1_500), - primary40 = ColorResourceHelper.getColor(context, R.color.system_accent1_600), - primary30 = ColorResourceHelper.getColor(context, R.color.system_accent1_700), - primary20 = ColorResourceHelper.getColor(context, R.color.system_accent1_800), - primary10 = ColorResourceHelper.getColor(context, R.color.system_accent1_900), - primary0 = ColorResourceHelper.getColor(context, R.color.system_accent1_1000), - - // The secondary tonal range from the generated dynamic color palette. - secondary100 = ColorResourceHelper.getColor(context, R.color.system_accent2_0), - secondary99 = ColorResourceHelper.getColor(context, R.color.system_accent2_10), - secondary95 = ColorResourceHelper.getColor(context, R.color.system_accent2_50), - secondary90 = ColorResourceHelper.getColor(context, R.color.system_accent2_100), - secondary80 = ColorResourceHelper.getColor(context, R.color.system_accent2_200), - secondary70 = ColorResourceHelper.getColor(context, R.color.system_accent2_300), - secondary60 = ColorResourceHelper.getColor(context, R.color.system_accent2_400), - secondary50 = ColorResourceHelper.getColor(context, R.color.system_accent2_500), - secondary40 = ColorResourceHelper.getColor(context, R.color.system_accent2_600), - secondary30 = ColorResourceHelper.getColor(context, R.color.system_accent2_700), - secondary20 = ColorResourceHelper.getColor(context, R.color.system_accent2_800), - secondary10 = ColorResourceHelper.getColor(context, R.color.system_accent2_900), - secondary0 = ColorResourceHelper.getColor(context, R.color.system_accent2_1000), - - // The tertiary tonal range from the generated dynamic color palette. - tertiary100 = ColorResourceHelper.getColor(context, R.color.system_accent3_0), - tertiary99 = ColorResourceHelper.getColor(context, R.color.system_accent3_10), - tertiary95 = ColorResourceHelper.getColor(context, R.color.system_accent3_50), - tertiary90 = ColorResourceHelper.getColor(context, R.color.system_accent3_100), - tertiary80 = ColorResourceHelper.getColor(context, R.color.system_accent3_200), - tertiary70 = ColorResourceHelper.getColor(context, R.color.system_accent3_300), - tertiary60 = ColorResourceHelper.getColor(context, R.color.system_accent3_400), - tertiary50 = ColorResourceHelper.getColor(context, R.color.system_accent3_500), - tertiary40 = ColorResourceHelper.getColor(context, R.color.system_accent3_600), - tertiary30 = ColorResourceHelper.getColor(context, R.color.system_accent3_700), - tertiary20 = ColorResourceHelper.getColor(context, R.color.system_accent3_800), - tertiary10 = ColorResourceHelper.getColor(context, R.color.system_accent3_900), - tertiary0 = ColorResourceHelper.getColor(context, R.color.system_accent3_1000), - ) - -private object ColorResourceHelper { - @DoNotInline - fun getColor(context: Context, @ColorRes id: Int): Color { - return Color(context.resources.getColor(id, context.theme)) - } -} diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt index 0701045f5..51f098371 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt +++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt @@ -737,6 +737,7 @@ object KotlinUtils { newPerms, group.hasInstallToRuntimeSplit, group.specialLocationGrant, + group.specialFixedStorageGrant, ) } @@ -857,6 +858,7 @@ object KotlinUtils { newPerms, group.hasInstallToRuntimeSplit, group.specialLocationGrant, + group.specialFixedStorageGrant, ) // If any permission in the group is one time granted, start one time permission session. if (newGroup.permissions.any { it.value.isOneTime && it.value.isGranted }) { @@ -1139,6 +1141,7 @@ object KotlinUtils { newPerms, group.hasInstallToRuntimeSplit, group.specialLocationGrant, + group.specialFixedStorageGrant, ) if (wasOneTime && !anyPermsOfPackageOneTimeGranted(app, newGroup.packageInfo, newGroup)) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java index 61e33d10b..5f870b1e3 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java @@ -25,7 +25,6 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -34,6 +33,7 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.preference.TwoStatePreference; @@ -125,13 +125,17 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat ViewModelProvider.Factory viewModelFactory = new DefaultAppViewModel.Factory(mRole, mUser, activity.getApplication()); mViewModel = new ViewModelProvider(this, viewModelFactory).get(DefaultAppViewModel.class); - mViewModel.getRoleLiveData().observe(this, this::onRoleChanged); + mViewModel.getLiveData().observe(this, applicationItems -> onApplicationListChanged()); mViewModel.getManageRoleHolderStateLiveData().observe(this, this::onManageRoleHolderStateChanged); } - private void onRoleChanged( - @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { + private void onApplicationListChanged() { + List<RoleApplicationItem> applicationItems = mViewModel.getLiveData().getValue(); + if (applicationItems == null) { + return; + } + PF preferenceFragment = requirePreferenceFragment(); PreferenceManager preferenceManager = preferenceFragment.getPreferenceManager(); Context context = preferenceManager.getContext(); @@ -142,37 +146,12 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat preferenceScreen = preferenceManager.createPreferenceScreen(context); preferenceFragment.setPreferenceScreen(preferenceScreen); } else { - for (int i = preferenceScreen.getPreferenceCount() - 1; i >= 0; --i) { - Preference preference = preferenceScreen.getPreference(i); - - preferenceScreen.removePreference(preference); - preference.setOrder(Preference.DEFAULT_ORDER); - oldPreferences.put(preference.getKey(), preference); - } + clearPreferences(preferenceScreen, oldPreferences); } - if (mRole.shouldShowNone()) { - Drawable icon = AppCompatResources.getDrawable(context, R.drawable.ic_remove_circle); - String title = getString(R.string.default_app_none); - boolean noHolderApplication = !hasHolderApplication(qualifyingApplications); - addPreference(PREFERENCE_KEY_NONE, icon, title, noHolderApplication, null, - oldPreferences, preferenceScreen, context); - } - - int qualifyingApplicationsSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationsSize; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(i); - ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first; - boolean isHolderApplication = qualifyingApplication.second; - - int userId = - UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid).getIdentifier(); - String key = qualifyingApplicationInfo.packageName + "@" + userId; - Drawable icon = Utils.getBadgedIcon(context, qualifyingApplicationInfo); - String title = Utils.getFullAppLabel(qualifyingApplicationInfo, context); - addPreference(key, icon, title, isHolderApplication, qualifyingApplicationInfo, - oldPreferences, preferenceScreen, context); - } + boolean noneChecked = !hasHolderApplication(applicationItems); + addNonePreferenceIfNeeded(preferenceScreen, noneChecked, oldPreferences, context); + addApplicationPreferences(preferenceScreen, applicationItems, oldPreferences, context); addNonPaymentNfcServicesPreference(preferenceScreen, oldPreferences, context); addDescriptionPreference(preferenceScreen, oldPreferences); @@ -180,24 +159,64 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat preferenceFragment.onPreferenceScreenChanged(); } - private static boolean hasHolderApplication( - @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { - int qualifyingApplicationsSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationsSize; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(i); - boolean isHolderApplication = qualifyingApplication.second; + private static void clearPreferences(@NonNull PreferenceGroup preferenceGroup, + @NonNull ArrayMap<String, Preference> oldPreferences) { + for (int i = preferenceGroup.getPreferenceCount() - 1; i >= 0; --i) { + Preference preference = preferenceGroup.getPreference(i); + + preferenceGroup.removePreference(preference); + preference.setOrder(Preference.DEFAULT_ORDER); + oldPreferences.put(preference.getKey(), preference); + } + } - if (isHolderApplication) { + private static boolean hasHolderApplication( + @NonNull List<RoleApplicationItem> applicationItems) { + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + if (applicationItem.isHolderApplication()) { return true; } } return false; } - private void addPreference(@NonNull String key, @NonNull Drawable icon, - @NonNull CharSequence title, boolean checked, @Nullable ApplicationInfo applicationInfo, - @NonNull ArrayMap<String, Preference> oldPreferences, - @NonNull PreferenceScreen preferenceScreen, @NonNull Context context) { + private void addNonePreferenceIfNeeded(@NonNull PreferenceGroup preferenceGroup, + boolean checked, @NonNull ArrayMap<String, Preference> oldPreferences, + @NonNull Context context) { + if (!mRole.shouldShowNone()) { + return; + } + + Drawable icon = AppCompatResources.getDrawable(context, R.drawable.ic_remove_circle); + String title = getString(R.string.default_app_none); + addApplicationPreference(preferenceGroup, PREFERENCE_KEY_NONE, icon, title, checked, null, + oldPreferences, context); + } + + private void addApplicationPreferences(@NonNull PreferenceGroup preferenceGroup, + @NonNull List<RoleApplicationItem> applicationItems, + @NonNull ArrayMap<String, Preference> oldPreferences, @NonNull Context context) { + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); + int userId = UserHandle.getUserHandleForUid(applicationInfo.uid).getIdentifier(); + String key = applicationInfo.packageName + "@" + userId; + Drawable icon = Utils.getBadgedIcon(context, applicationInfo); + String title = Utils.getFullAppLabel(applicationInfo, context); + boolean isHolderApplication = applicationItem.isHolderApplication(); + + addApplicationPreference(preferenceGroup, key, icon, title, isHolderApplication, + applicationInfo, oldPreferences, context); + } + } + + private void addApplicationPreference(@NonNull PreferenceGroup preferenceGroup, + @NonNull String key, @NonNull Drawable icon, @NonNull CharSequence title, + boolean checked, @Nullable ApplicationInfo applicationInfo, + @NonNull ArrayMap<String, Preference> oldPreferences, @NonNull Context context) { RoleApplicationPreference roleApplicationPreference = (RoleApplicationPreference) oldPreferences.get(key); TwoStatePreference preference; @@ -233,7 +252,7 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat applicationInfo, user, context); } - preferenceScreen.addPreference(preference); + preferenceGroup.addPreference(preference); } private void onManageRoleHolderStateChanged(int state) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java index 48472bc5e..2a987167e 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java @@ -131,18 +131,16 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat } else { oldWorkPreferenceCategory = preferenceScreen.findPreference(PREFERENCE_KEY_WORK_CATEGORY); - clearPreferenceCategory( - oldWorkPreferenceCategory, preferenceScreen, oldWorkPreferences); + clearPreferenceCategory(oldWorkPreferenceCategory, oldWorkPreferences); oldPrivatePreferenceCategory = preferenceScreen.findPreference(PREFERENCE_KEY_PRIVATE_CATEGORY); - clearPreferenceCategory( - oldPrivatePreferenceCategory, preferenceScreen, oldPrivatePreferences); + clearPreferenceCategory(oldPrivatePreferenceCategory, oldPrivatePreferences); clearPreferences(preferenceScreen, oldPreferences); } - addPreferences(preferenceScreen, roleItems, oldPreferences, this, mViewModel.getUser(), + addRolePreferences(preferenceScreen, roleItems, oldPreferences, this, mViewModel.getUser(), context); addMoreDefaultAppsPreference(preferenceScreen, oldPreferences, context); addManageDomainUrlsPreference(preferenceScreen, oldPreferences, context); @@ -155,7 +153,7 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat } String workTitle = Utils.getEnterpriseString(context, DefaultAppSettings.WORK_PROFILE_DEFAULT_APPS_TITLE, defaultWorkTitle); - addPreferenceCategory(oldWorkPreferenceCategory, PREFERENCE_KEY_WORK_CATEGORY, + addRolePreferenceCategory(oldWorkPreferenceCategory, PREFERENCE_KEY_WORK_CATEGORY, workTitle, preferenceScreen, workRoleItems, oldWorkPreferences, this, mViewModel.getWorkProfile(), context); } @@ -166,22 +164,22 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat } else { privateTitle = context.getString(R.string.default_apps_for_private_profile); } - addPreferenceCategory(oldPrivatePreferenceCategory, PREFERENCE_KEY_PRIVATE_CATEGORY, - privateTitle, preferenceScreen, privateRoleItems, oldPrivatePreferences, this, - mViewModel.getPrivateProfile(), context); + addRolePreferenceCategory(oldPrivatePreferenceCategory, + PREFERENCE_KEY_PRIVATE_CATEGORY, privateTitle, preferenceScreen, + privateRoleItems, oldPrivatePreferences, this, mViewModel.getPrivateProfile(), + context); } preferenceFragment.onPreferenceScreenChanged(); } private static void clearPreferenceCategory(@Nullable PreferenceCategory preferenceCategory, - @NonNull PreferenceScreen preferenceScreen, @NonNull ArrayMap<String, Preference> oldPreferences) { if (preferenceCategory == null) { return; } clearPreferences(preferenceCategory, oldPreferences); - preferenceScreen.removePreference(preferenceCategory); + preferenceCategory.getParent().removePreference(preferenceCategory); preferenceCategory.setOrder(Preference.DEFAULT_ORDER); } @@ -197,7 +195,7 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat } @NonNull - private void addPreferenceCategory( + private void addRolePreferenceCategory( @Nullable PreferenceCategory oldPreferenceCategory, @NonNull String key, @Nullable String title, @NonNull PreferenceScreen preferenceScreen, @NonNull List<RoleItem> roleItems, @NonNull ArrayMap<String, Preference> oldPreferences, @@ -210,11 +208,10 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat preferenceCategory.setTitle(title); } preferenceScreen.addPreference(preferenceCategory); - addPreferences(preferenceCategory, roleItems, oldPreferences, listener, - user, context); + addRolePreferences(preferenceCategory, roleItems, oldPreferences, listener, user, context); } - private void addPreferences(@NonNull PreferenceGroup preferenceGroup, + private void addRolePreferences(@NonNull PreferenceGroup preferenceGroup, @NonNull List<RoleItem> roleItems, @NonNull ArrayMap<String, Preference> oldPreferences, @NonNull Preference.OnPreferenceClickListener listener, @NonNull UserHandle user, @NonNull Context context) { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java index 718af090e..4a280bd58 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java @@ -78,11 +78,11 @@ public class DefaultAppListViewModel extends AndroidViewModel { mLiveData = Transformations.map( new MergeRoleListLiveData(liveData, Transformations.map(workLiveData, - new RoleListFilterFunction(exclusivityPredicate))), + new ListLiveDataFilterFunction<>(exclusivityPredicate))), sortFunction); mWorkLiveData = Transformations.map( Transformations.map(workLiveData, - new RoleListFilterFunction(exclusivityPredicate.negate())), + new ListLiveDataFilterFunction<>(exclusivityPredicate.negate())), sortFunction); } else if (Flags.crossUserRoleUxBugfixEnabled() && isWorkProfile) { // Show profile group exclusive roles from the profile parent (full user) in primary @@ -92,7 +92,7 @@ public class DefaultAppListViewModel extends AndroidViewModel { mLiveData = Transformations.map( new MergeRoleListLiveData(liveData, Transformations.map(profileParentLiveData, - new RoleListFilterFunction(exclusivityPredicate))), + new ListLiveDataFilterFunction<>(exclusivityPredicate))), sortFunction); mWorkLiveData = null; } else { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java index cdee94b13..790c55d84 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppViewModel.java @@ -18,10 +18,8 @@ package com.android.permissioncontroller.role.ui; import android.app.Application; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.os.UserHandle; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; @@ -48,7 +46,7 @@ public class DefaultAppViewModel extends AndroidViewModel { private final UserHandle mUser; @NonNull - private final LiveData<List<Pair<ApplicationInfo, Boolean>>> mRoleLiveData; + private final LiveData<List<RoleApplicationItem>> mLiveData; @NonNull private final ManageRoleHolderStateLiveData mManageRoleHolderStateLiveData = @@ -60,30 +58,30 @@ public class DefaultAppViewModel extends AndroidViewModel { mRole = role; // If EXCLUSIVITY_PROFILE_GROUP this user should be profile parent - mUser = mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP + mUser = role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP ? UserUtils.getProfileParentOrSelf(user, application) : user; - RoleLiveData liveData = new RoleLiveData(mRole, mUser, application); + RoleLiveData liveData = new RoleLiveData(role, mUser, application); RoleSortFunction sortFunction = new RoleSortFunction(application); - if (mRole.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { + if (role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP) { // Context user might be work profile, ensure we get a non-null UserHandle if work // profile exists. getWorkProfile returns null if context user is work profile. UserHandle workProfile = UserUtils.getWorkProfileOrSelf(application); if (workProfile != null) { RoleLiveData workLiveData = new RoleLiveData(role, workProfile, application); - mRoleLiveData = Transformations.map(new MergeRoleLiveData(liveData, workLiveData), + mLiveData = Transformations.map(new MergeRoleLiveData(liveData, workLiveData), sortFunction); } else { - mRoleLiveData = Transformations.map(liveData, sortFunction); + mLiveData = Transformations.map(liveData, sortFunction); } } else { - mRoleLiveData = Transformations.map(liveData, sortFunction); + mLiveData = Transformations.map(liveData, sortFunction); } } @NonNull - public LiveData<List<Pair<ApplicationInfo, Boolean>>> getRoleLiveData() { - return mRoleLiveData; + public LiveData<List<RoleApplicationItem>> getLiveData() { + return mLiveData; } @NonNull diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java index b84fa80b9..8657db0ab 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListFilterFunction.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataFilterFunction.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.permissioncontroller.role.ui; import androidx.annotation.NonNull; @@ -25,29 +26,32 @@ import java.util.List; import java.util.function.Predicate; /** - * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} - * that filters a live data for role list. + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} + * that filters a live data for a list. + * + * @param <T> the type of the list elements */ -public class RoleListFilterFunction implements Function1<List<RoleItem>, List<RoleItem>> { - private final Predicate<RoleItem> mPredicate; +public class ListLiveDataFilterFunction<T> implements Function1<List<T>, List<T>> { + private final Predicate<T> mPredicate; - public RoleListFilterFunction(@NonNull Predicate<RoleItem> predicate) { + public ListLiveDataFilterFunction(@NonNull Predicate<T> predicate) { mPredicate = predicate; } @NonNull @Override - public List<RoleItem> invoke(@Nullable List<RoleItem> roleItems) { - List<RoleItem> filteredRoleItems = new ArrayList<>(); - if (roleItems != null) { - int roleItemsSize = roleItems.size(); - for (int i = 0; i < roleItemsSize; i++) { - RoleItem roleItem = roleItems.get(i); - if (mPredicate.test(roleItem)) { - filteredRoleItems.add(roleItem); + public List<T> invoke(@Nullable List<T> items) { + List<T> filteredItems = new ArrayList<>(); + if (items != null) { + int itemsSize = items.size(); + for (int i = 0; i < itemsSize; i++) { + T item = items.get(i); + if (mPredicate.test(item)) { + filteredItems.add(item); } } } - return filteredRoleItems; + return filteredItems; } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java new file mode 100644 index 000000000..36e7afcc8 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/ListLiveDataSortFunction.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.permissioncontroller.role.ui; + +import androidx.annotation.NonNull; + +import kotlin.jvm.functions.Function1; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} + * that sorts a live data for a list. + * + * @param <T> the type of the list elements + */ +public class ListLiveDataSortFunction<T> implements Function1<List<T>, List<T>> { + + @NonNull + private final Comparator<T> mComparator; + + public ListLiveDataSortFunction(@NonNull Comparator<T> comparator) { + mComparator = comparator; + } + + @Override + public List<T> invoke(List<T> items) { + List<T> sortedItems = new ArrayList<>(items); + sortedItems.sort(mComparator); + return sortedItems; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java index 31a02729a..72c2264ce 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/MergeRoleLiveData.java @@ -16,9 +16,6 @@ package com.android.permissioncontroller.role.ui; -import android.content.pm.ApplicationInfo; -import android.util.Pair; - import androidx.annotation.NonNull; import androidx.lifecycle.MediatorLiveData; @@ -28,7 +25,7 @@ import java.util.List; /** * {@link MediatorLiveData} that merges multiple {@link RoleLiveData} instances. */ -public class MergeRoleLiveData extends MediatorLiveData<List<Pair<ApplicationInfo, Boolean>>> { +public class MergeRoleLiveData extends MediatorLiveData<List<RoleApplicationItem>> { @NonNull private final RoleLiveData[] mLiveDatas; @@ -40,23 +37,23 @@ public class MergeRoleLiveData extends MediatorLiveData<List<Pair<ApplicationInf for (int i = 0; i < liveDatasLength; i++) { RoleLiveData liveData = mLiveDatas[i]; - addSource(liveData, roleItems -> onRoleChanged()); + addSource(liveData, items -> onRoleChanged()); } } private void onRoleChanged() { - List<Pair<ApplicationInfo, Boolean>> mergedQualifyingApplications = new ArrayList<>(); + List<RoleApplicationItem> mergedItems = new ArrayList<>(); int liveDatasLength = mLiveDatas.length; for (int i = 0; i < liveDatasLength; i++) { RoleLiveData liveData = mLiveDatas[i]; - List<Pair<ApplicationInfo, Boolean>> qualifyingApplications = liveData.getValue(); - if (qualifyingApplications == null) { + List<RoleApplicationItem> items = liveData.getValue(); + if (items == null) { return; } - mergedQualifyingApplications.addAll(qualifyingApplications); + mergedItems.addAll(items); } - setValue(mergedQualifyingApplications); + setValue(mergedItems); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java index 60139f0c8..f411b0cd0 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java @@ -30,7 +30,6 @@ import android.os.Process; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -236,7 +235,7 @@ public class RequestRoleFragment extends DialogFragment { ViewModelProvider.Factory viewModelFactory = new RequestRoleViewModel.Factory(mRole, requireActivity().getApplication()); mViewModel = new ViewModelProvider(this, viewModelFactory).get(RequestRoleViewModel.class); - mViewModel.getRoleLiveData().observe(this, this::onRoleDataChanged); + mViewModel.getLiveData().observe(this, this::onApplicationListChanged); mViewModel.getManageRoleHolderStateLiveData().observe(this, this::onManageRoleHolderStateChanged); } @@ -272,9 +271,9 @@ public class RequestRoleFragment extends DialogFragment { setDeniedOnceAndFinish(); } - private void onRoleDataChanged( - @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { - mAdapter.replace(qualifyingApplications); + private void onApplicationListChanged( + @NonNull List<RoleApplicationItem> applicationItems) { + mAdapter.replace(applicationItems); updateUi(); } @@ -364,8 +363,8 @@ public class RequestRoleFragment extends DialogFragment { boolean dontAskAgain = mDontAskAgainCheck != null && mDontAskAgainCheck.isChecked(); mAdapter.setDontAskAgain(dontAskAgain); AlertDialog dialog = getDialog(); - boolean hasRoleData = mViewModel.getRoleLiveData().getValue() != null; - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled && hasRoleData + boolean hasApplicationList = mViewModel.getLiveData().getValue() != null; + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled && hasApplicationList && (dontAskAgain || !mAdapter.isHolderApplicationChecked())); dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setEnabled(enabled); } @@ -420,12 +419,12 @@ public class RequestRoleFragment extends DialogFragment { } int count = mAdapter.getCount(); for (int i = 0; i < count; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = mAdapter.getItem(i); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = mAdapter.getItem(i); + if (applicationItem == null) { // Skip the "None" item. continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); if (Objects.equals(UserPackage.from(applicationInfo), userPackage)) { return applicationInfo.uid; } @@ -493,8 +492,7 @@ public class RequestRoleFragment extends DialogFragment { // We'll use a null to represent the "None" item. @NonNull - private final List<Pair<ApplicationInfo, Boolean>> mQualifyingApplications = - new ArrayList<>(); + private final List<RoleApplicationItem> mApplicationItems = new ArrayList<>(); @Nullable private UserPackage mHolderUserPackage; @@ -546,12 +544,12 @@ public class RequestRoleFragment extends DialogFragment { } public void onItemClicked(int position) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(position); + if (applicationItem == null) { mUserChecked = true; mCheckedUserPackage = null; } else { - ApplicationInfo applicationInfo = qualifyingApplication.first; + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); UserHandle user = UserHandle.getUserHandleForUid(applicationInfo.uid); Intent restrictionIntent = mRole.getApplicationRestrictionIntentAsUser( applicationInfo, user, mListView.getContext()); @@ -566,24 +564,24 @@ public class RequestRoleFragment extends DialogFragment { notifyDataSetChanged(); } - public void replace(@NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { - mQualifyingApplications.clear(); + public void replace(@NonNull List<RoleApplicationItem> applicationItems) { + mApplicationItems.clear(); if (mRole.shouldShowNone()) { - mQualifyingApplications.add(0, null); + mApplicationItems.add(0, null); } - mQualifyingApplications.addAll(qualifyingApplications); - mHolderUserPackage = getHolderUserPackage(qualifyingApplications); + mApplicationItems.addAll(applicationItems); + mHolderUserPackage = getHolderUserPackage(applicationItems); if (mUserChecked && mCheckedUserPackage != null) { boolean isCheckedPackageNameFound = false; int count = getCount(); for (int i = 0; i < count; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(i); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(i); + if (applicationItem == null) { continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; - UserPackage userPackage = UserPackage.from(applicationInfo); + UserPackage userPackage = + UserPackage.from(applicationItem.getApplicationInfo()); if (Objects.equals(userPackage, mCheckedUserPackage)) { mUserChecked = true; @@ -606,19 +604,15 @@ public class RequestRoleFragment extends DialogFragment { @Nullable private static UserPackage getHolderUserPackage( - @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { - int qualifyingApplicationSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationSize; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get( - i); - if (qualifyingApplication == null) { + @NonNull List<RoleApplicationItem> applicationItems) { + int applicationItemSize = applicationItems.size(); + for (int i = 0; i < applicationItemSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + if (applicationItem == null) { continue; } - ApplicationInfo applicationInfo = qualifyingApplication.first; - boolean isHolderApplication = qualifyingApplication.second; - - if (isHolderApplication) { - return UserPackage.from(applicationInfo); + if (applicationItem.isHolderApplication()) { + return UserPackage.from(applicationItem.getApplicationInfo()); } } return null; @@ -645,13 +639,13 @@ public class RequestRoleFragment extends DialogFragment { @Override public int getCount() { - return mQualifyingApplications.size(); + return mApplicationItems.size(); } @Nullable @Override - public Pair<ApplicationInfo, Boolean> getItem(int position) { - return mQualifyingApplications.get(position); + public RoleApplicationItem getItem(int position) { + return mApplicationItems.get(position); } @Override @@ -660,9 +654,9 @@ public class RequestRoleFragment extends DialogFragment { // Work around AbsListView.confirmCheckedPositionsById() not respecting our count. return ListView.INVALID_ROW_ID; } - Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position); - return qualifyingApplication == null ? 0 - : qualifyingApplication.first.packageName.hashCode(); + RoleApplicationItem applicationItem = getItem(position); + return applicationItem == null ? 0 + : applicationItem.getApplicationInfo().packageName.hashCode(); } @Override @@ -670,12 +664,11 @@ public class RequestRoleFragment extends DialogFragment { if (!mDontAskAgain) { return true; } - Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position); - if (qualifyingApplication == null) { + RoleApplicationItem applicationItem = getItem(position); + if (applicationItem == null) { return mHolderUserPackage == null; } else { - boolean isHolderApplication = qualifyingApplication.second; - return isHolderApplication; + return applicationItem.isHolderApplication(); } } @@ -697,14 +690,14 @@ public class RequestRoleFragment extends DialogFragment { LAYOUT_TRANSITION_DURATION_MILLIS); } - Pair<ApplicationInfo, Boolean> qualifyingApplication = getItem(position); + RoleApplicationItem applicationItem = getItem(position); ApplicationInfo applicationInfo; boolean restricted; boolean checked; Drawable icon; String title; String subtitle; - if (qualifyingApplication == null) { + if (applicationItem == null) { applicationInfo = null; restricted = false; checked = mCheckedUserPackage == null; @@ -713,15 +706,14 @@ public class RequestRoleFragment extends DialogFragment { subtitle = mHolderUserPackage == null ? context.getString( R.string.request_role_current_default) : null; } else { - applicationInfo = qualifyingApplication.first; + applicationInfo = applicationItem.getApplicationInfo(); UserPackage userPackage = UserPackage.from(applicationInfo); restricted = mRole.getApplicationRestrictionIntentAsUser(applicationInfo, userPackage.user, context) != null; checked = Objects.equals(userPackage, mCheckedUserPackage); icon = Utils.getBadgedIcon(context, applicationInfo); title = Utils.getAppLabel(applicationInfo, context); - boolean isHolderApplication = qualifyingApplication.second; - subtitle = isHolderApplication + subtitle = applicationItem.isHolderApplication() ? context.getString(R.string.request_role_current_default) : checked ? context.getString(mRole.getRequestDescriptionResource()) : null; } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java new file mode 100644 index 000000000..b6c489ea1 --- /dev/null +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationItem.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.permissioncontroller.role.ui; + +import android.content.pm.ApplicationInfo; + +import androidx.annotation.NonNull; + +/** + * Information about an application to be displayed in a list of applications qualifying for a role. + */ +public class RoleApplicationItem { + + /** + * The {@link ApplicationInfo} for this application. + */ + @NonNull + private final ApplicationInfo mApplicationInfo; + + /** + * Whether this application is holding the role. + */ + private final boolean mIsHolderApplication; + + public RoleApplicationItem(@NonNull ApplicationInfo applicationInfo, + boolean isHolderApplication) { + mApplicationInfo = applicationInfo; + mIsHolderApplication = isHolderApplication; + } + + @NonNull + public ApplicationInfo getApplicationInfo() { + return mApplicationInfo; + } + + public boolean isHolderApplication() { + return mIsHolderApplication; + } +} diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java index ca059aa32..07b4db1f4 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleListSortFunction.java @@ -23,30 +23,23 @@ import androidx.annotation.NonNull; import kotlin.jvm.functions.Function1; -import java.util.ArrayList; import java.util.Comparator; -import java.util.List; /** - * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} * that sorts a live data for role list. */ -public class RoleListSortFunction implements Function1<List<RoleItem>, List<RoleItem>> { - - @NonNull - private final Comparator<RoleItem> mComparator; +public class RoleListSortFunction extends ListLiveDataSortFunction<RoleItem> { public RoleListSortFunction(@NonNull Context context) { - Collator collator = Collator.getInstance(context.getResources().getConfiguration() - .getLocales().get(0)); - mComparator = Comparator.comparing(roleItem -> context.getString( - roleItem.getRole().getShortLabelResource()), collator); + super(createComparator(context)); } - @Override - public List<RoleItem> invoke(List<RoleItem> p1) { - List<RoleItem> sorted = new ArrayList<>(p1); - sorted.sort(mComparator); - return sorted; + private static Comparator<RoleItem> createComparator(@NonNull Context context) { + Collator collator = Collator.getInstance(context.getResources().getConfiguration() + .getLocales().get(0)); + return Comparator.comparing(item -> context.getString( + item.getRole().getShortLabelResource()), collator); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java index bb492f76d..1b6d42934 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleLiveData.java @@ -22,7 +22,6 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.os.UserHandle; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; @@ -38,7 +37,7 @@ import java.util.List; /** * {@link LiveData} for a role. */ -public class RoleLiveData extends AsyncTaskLiveData<List<Pair<ApplicationInfo, Boolean>>> +public class RoleLiveData extends AsyncTaskLiveData<List<RoleApplicationItem>> implements OnRoleHoldersChangedListener { private static final String LOG_TAG = RoleLiveData.class.getSimpleName(); @@ -77,12 +76,12 @@ public class RoleLiveData extends AsyncTaskLiveData<List<Pair<ApplicationInfo, B @Override @WorkerThread - protected List<Pair<ApplicationInfo, Boolean>> loadValueInBackground() { + protected List<RoleApplicationItem> loadValueInBackground() { RoleManager roleManager = mContext.getSystemService(RoleManager.class); List<String> holderPackageNames = roleManager.getRoleHoldersAsUser(mRole.getName(), mUser); List<String> qualifyingPackageNames = mRole.getQualifyingPackagesAsUser(mUser, mContext); - List<Pair<ApplicationInfo, Boolean>> qualifyingApplications = new ArrayList<>(); + List<RoleApplicationItem> applicationItems = new ArrayList<>(); int qualifyingPackageNamesSize = qualifyingPackageNames.size(); for (int i = 0; i < qualifyingPackageNamesSize; i++) { String qualifyingPackageName = qualifyingPackageNames.get(i); @@ -98,9 +97,10 @@ public class RoleLiveData extends AsyncTaskLiveData<List<Pair<ApplicationInfo, B continue; } boolean isHolderApplication = holderPackageNames.contains(qualifyingPackageName); - qualifyingApplications.add(new Pair<>(qualifyingApplicationInfo, isHolderApplication)); + applicationItems.add( + new RoleApplicationItem(qualifyingApplicationInfo, isHolderApplication)); } - return qualifyingApplications; + return applicationItems; } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java index 10db9dbcd..9a06a6b01 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleSortFunction.java @@ -17,10 +17,8 @@ package com.android.permissioncontroller.role.ui; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.icu.text.Collator; import android.os.UserHandle; -import android.util.Pair; import androidx.annotation.NonNull; @@ -28,34 +26,26 @@ import com.android.permissioncontroller.permission.utils.Utils; import kotlin.jvm.functions.Function1; -import java.util.ArrayList; import java.util.Comparator; -import java.util.List; /** - * A function for {@link androidx.lifecycle#map(androidx.lifecycle.LiveData, Function1)} + * A function for + * {@link androidx.lifecycle.Transformations#map(androidx.lifecycle.LiveData, Function1)} * that sorts a live data for role. */ -public class RoleSortFunction implements Function1<List<Pair<ApplicationInfo, Boolean>>, - List<Pair<ApplicationInfo, Boolean>>> { - - @NonNull - private final Comparator<Pair<ApplicationInfo, Boolean>> mComparator; +public class RoleSortFunction extends ListLiveDataSortFunction<RoleApplicationItem> { public RoleSortFunction(@NonNull Context context) { - Collator collator = Collator.getInstance(context.getResources().getConfiguration() - .getLocales().get(0)); - Comparator<Pair<ApplicationInfo, Boolean>> labelComparator = Comparator.comparing(role -> - Utils.getAppLabel(role.first, context), collator); - Comparator<Pair<ApplicationInfo, Boolean>> userIdComparator = Comparator.comparingInt(role - -> UserHandle.getUserHandleForUid(role.first.uid).getIdentifier()); - mComparator = labelComparator.thenComparing(userIdComparator); + super(createComparator(context)); } - @Override - public List<Pair<ApplicationInfo, Boolean>> invoke(List<Pair<ApplicationInfo, Boolean>> p1) { - List<Pair<ApplicationInfo, Boolean>> sorted = new ArrayList<>(p1); - sorted.sort(mComparator); - return sorted; + private static Comparator<RoleApplicationItem> createComparator(@NonNull Context context) { + Collator collator = Collator.getInstance(context.getResources().getConfiguration() + .getLocales().get(0)); + Comparator<RoleApplicationItem> labelComparator = Comparator.comparing(item -> + Utils.getAppLabel(item.getApplicationInfo(), context), collator); + Comparator<RoleApplicationItem> userIdComparator = Comparator.comparingInt(item + -> UserHandle.getUserHandleForUid(item.getApplicationInfo().uid).getIdentifier()); + return labelComparator.thenComparing(userIdComparator); } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java index 0963635e7..7a13eb2b5 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessChildFragment.java @@ -23,7 +23,6 @@ import android.content.pm.ApplicationInfo; import android.os.Bundle; import android.os.UserHandle; import android.util.ArrayMap; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -37,6 +36,7 @@ import androidx.preference.TwoStatePreference; import com.android.permissioncontroller.permission.utils.Utils; import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData; +import com.android.permissioncontroller.role.ui.RoleApplicationItem; import com.android.permissioncontroller.role.ui.RoleApplicationPreference; import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils; import com.android.role.controller.model.Role; @@ -107,12 +107,12 @@ public class SpecialAppAccessChildFragment<PF extends PreferenceFragmentCompat activity.getApplication()); mViewModel = new ViewModelProvider(this, viewModelFactory) .get(SpecialAppAccessViewModel.class); - mViewModel.getRoleLiveData().observe(this, this::onRoleChanged); + mViewModel.getLiveData().observe(this, this::onApplicationListChanged); mViewModel.observeManageRoleHolderState(this, this::onManageRoleHolderStateChanged); } - private void onRoleChanged( - @NonNull List<Pair<ApplicationInfo, Boolean>> qualifyingApplications) { + private void onApplicationListChanged( + @NonNull List<RoleApplicationItem> applicationItems) { PF preferenceFragment = requirePreferenceFragment(); PreferenceManager preferenceManager = preferenceFragment.getPreferenceManager(); Context context = preferenceManager.getContext(); @@ -138,14 +138,12 @@ public class SpecialAppAccessChildFragment<PF extends PreferenceFragmentCompat } } - int qualifyingApplicationsSize = qualifyingApplications.size(); - for (int i = 0; i < qualifyingApplicationsSize; i++) { - Pair<ApplicationInfo, Boolean> qualifyingApplication = qualifyingApplications.get(i); - ApplicationInfo qualifyingApplicationInfo = qualifyingApplication.first; - boolean isHolderPackage = qualifyingApplication.second; - - String key = qualifyingApplicationInfo.packageName + '_' - + qualifyingApplicationInfo.uid; + int applicationItemsSize = applicationItems.size(); + for (int i = 0; i < applicationItemsSize; i++) { + RoleApplicationItem applicationItem = applicationItems.get(i); + ApplicationInfo applicationInfo = applicationItem.getApplicationInfo(); + String key = applicationInfo.packageName + '_' + + applicationInfo.uid; RoleApplicationPreference roleApplicationPreference = (RoleApplicationPreference) oldPreferences.get(key); TwoStatePreference preference; @@ -153,24 +151,23 @@ public class SpecialAppAccessChildFragment<PF extends PreferenceFragmentCompat roleApplicationPreference = preferenceFragment.createApplicationPreference(); preference = roleApplicationPreference.asTwoStatePreference(); preference.setKey(key); - preference.setIcon(Utils.getBadgedIcon(context, qualifyingApplicationInfo)); - preference.setTitle(Utils.getFullAppLabel(qualifyingApplicationInfo, context)); + preference.setIcon(Utils.getBadgedIcon(context, applicationInfo)); + preference.setTitle(Utils.getFullAppLabel(applicationInfo, context)); preference.setPersistent(false); preference.setOnPreferenceChangeListener((preference2, newValue) -> false); preference.setOnPreferenceClickListener(this); preference.getExtras().putParcelable(PREFERENCE_EXTRA_APPLICATION_INFO, - qualifyingApplicationInfo); + applicationInfo); } else { preference = roleApplicationPreference.asTwoStatePreference(); } - preference.setChecked(isHolderPackage); - UserHandle user = UserHandle.getUserHandleForUid(qualifyingApplicationInfo.uid); + preference.setChecked(applicationItem.isHolderApplication()); + UserHandle user = UserHandle.getUserHandleForUid(applicationInfo.uid); roleApplicationPreference.setRestrictionIntent( - mRole.getApplicationRestrictionIntentAsUser(qualifyingApplicationInfo, user, - context)); + mRole.getApplicationRestrictionIntentAsUser(applicationInfo, user, context)); RoleUiBehaviorUtils.prepareApplicationPreferenceAsUser(mRole, roleApplicationPreference, - qualifyingApplicationInfo, user, context); + applicationInfo, user, context); preferenceScreen.addPreference(preference); } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java index c12265d43..f4abc0db1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/SpecialAppAccessViewModel.java @@ -17,12 +17,10 @@ package com.android.permissioncontroller.role.ui.specialappaccess; import android.app.Application; -import android.content.pm.ApplicationInfo; import android.os.Process; import android.os.UserHandle; import android.util.ArrayMap; import android.util.Log; -import android.util.Pair; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; @@ -34,6 +32,7 @@ import androidx.lifecycle.ViewModelProvider; import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData; import com.android.permissioncontroller.role.ui.MergeRoleLiveData; +import com.android.permissioncontroller.role.ui.RoleApplicationItem; import com.android.permissioncontroller.role.ui.RoleLiveData; import com.android.permissioncontroller.role.ui.RoleSortFunction; import com.android.permissioncontroller.role.utils.UserUtils; @@ -52,7 +51,7 @@ public class SpecialAppAccessViewModel extends AndroidViewModel { private final Role mRole; @NonNull - private final LiveData<List<Pair<ApplicationInfo, Boolean>>> mRoleLiveData; + private final LiveData<List<RoleApplicationItem>> mLiveData; @NonNull private final ArrayMap<String, ManageRoleHolderStateLiveData> mManageRoleHolderStateLiveDatas = @@ -68,17 +67,17 @@ public class SpecialAppAccessViewModel extends AndroidViewModel { UserHandle workProfile = UserUtils.getWorkProfile(application); RoleSortFunction sortFunction = new RoleSortFunction(application); if (workProfile == null) { - mRoleLiveData = Transformations.map(roleLiveData, sortFunction); + mLiveData = Transformations.map(roleLiveData, sortFunction); } else { RoleLiveData workRoleLiveData = new RoleLiveData(role, workProfile, application); - mRoleLiveData = Transformations.map(new MergeRoleLiveData(roleLiveData, + mLiveData = Transformations.map(new MergeRoleLiveData(roleLiveData, workRoleLiveData), sortFunction); } } @NonNull - public LiveData<List<Pair<ApplicationInfo, Boolean>>> getRoleLiveData() { - return mRoleLiveData; + public LiveData<List<RoleApplicationItem>> getLiveData() { + return mLiveData; } /** diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt index 156656e33..dc8f3bf88 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppFragment.kt @@ -27,11 +27,11 @@ import androidx.compose.ui.platform.ComposeView import androidx.core.os.BundleCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme import com.android.permissioncontroller.role.ui.DefaultAppViewModel import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModel import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModelFactory +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme import com.android.role.controller.model.Role import com.android.role.controller.model.Roles @@ -46,14 +46,13 @@ class WearDefaultAppFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? + savedInstanceState: Bundle?, ): View? { val roleName = arguments?.getString(Intent.EXTRA_ROLE_NAME) ?: "" val user = arguments?.let { BundleCompat.getParcelable(it, Intent.EXTRA_USER, UserHandle::class.java)!! - } - ?: UserHandle.SYSTEM + } ?: UserHandle.SYSTEM val activity = requireActivity() role = @@ -82,7 +81,7 @@ class WearDefaultAppFragment : Fragment() { user, role, viewModel, - confirmDialogViewModel + confirmDialogViewModel, ) ) } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt index 9e93f33c7..65548d9a1 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppHelper.kt @@ -17,12 +17,11 @@ package com.android.permissioncontroller.role.ui.wear import android.content.Context -import android.content.pm.ApplicationInfo import android.os.UserHandle -import android.util.Pair import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.role.ui.DefaultAppViewModel +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs import com.android.permissioncontroller.role.ui.wear.model.DefaultAppConfirmDialogViewModel import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils @@ -39,13 +38,13 @@ class WearDefaultAppHelper( fun getTitle() = context.getString(role.labelResource) fun getNonePreference( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>> + applicationItems: List<RoleApplicationItem> ): WearRoleApplicationPreference? = if (role.shouldShowNone()) { WearRoleApplicationPreference( context = context, defaultLabel = context.getString(R.string.default_app_none), - checked = !hasHolderApplication(qualifyingApplications), + checked = !hasHolderApplication(applicationItems), onDefaultCheckChanged = { _ -> viewModel.setNoneDefaultApp() }, ) .apply { icon = context.getDrawable(R.drawable.ic_remove_circle) } @@ -54,12 +53,12 @@ class WearDefaultAppHelper( } fun getPreferences( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>> + applicationItems: List<RoleApplicationItem> ): List<WearRoleApplicationPreference> { - return qualifyingApplications - .map { pair -> - val appInfo = pair.first - val selected = pair.second + return applicationItems + .map { applicationItem -> + val appInfo = applicationItem.applicationInfo + val selected = applicationItem.isHolderApplication val user = UserHandle.getUserHandleForUid(appInfo.uid) WearRoleApplicationPreference( context = context, @@ -127,7 +126,6 @@ class WearDefaultAppHelper( fun getDescription() = context.getString(role.descriptionResource) - private fun hasHolderApplication( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>> - ): Boolean = qualifyingApplications.map { it.second }.contains(true) + private fun hasHolderApplication(applicationItems: List<RoleApplicationItem>): Boolean = + applicationItems.map { it.isHolderApplication }.contains(true) } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt index d5b93e318..131897fb9 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppListScreen.kt @@ -29,11 +29,11 @@ import androidx.compose.ui.res.stringResource import androidx.lifecycle.LiveData import androidx.wear.compose.material.Text import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder import com.android.permissioncontroller.role.ui.RoleItem +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder @Composable fun WearDefaultAppListScreen( diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt index 60cfcda47..c3cbe4670 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearDefaultAppScreen.kt @@ -16,8 +16,6 @@ package com.android.permissioncontroller.role.ui.wear -import android.content.pm.ApplicationInfo -import android.util.Pair import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -25,21 +23,22 @@ import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionConfirmationDialog -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListFooter -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.ConfirmDialogArgs +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionConfirmationDialog +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionListFooter +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControl +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion @Composable fun WearDefaultAppScreen(helper: WearDefaultAppHelper) { - val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList()) + val roleLiveData = helper.viewModel.liveData.observeAsState(emptyList()) val showConfirmDialog = helper.confirmDialogViewModel.showConfirmDialogLiveData.observeAsState(false) var isLoading by remember { mutableStateOf(true) } @@ -60,11 +59,11 @@ fun WearDefaultAppScreen(helper: WearDefaultAppHelper) { @Composable private fun WearDefaultAppContent( isLoading: Boolean, - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>, + applicationItems: List<RoleApplicationItem>, helper: WearDefaultAppHelper, ) { ScrollableScreen(title = helper.getTitle(), isLoading = isLoading) { - helper.getNonePreference(qualifyingApplications)?.let { + helper.getNonePreference(applicationItems)?.let { item { WearPermissionToggleControl( label = it.title.toString(), @@ -76,7 +75,7 @@ private fun WearDefaultAppContent( ) } } - for (pref in helper.getPreferences(qualifyingApplications)) { + for (pref in helper.getPreferences(applicationItems)) { item { WearPermissionToggleControl( label = pref.title.toString(), diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt index af8dc5e92..99f2fe36f 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleFragment.kt @@ -231,11 +231,11 @@ class WearRequestRoleFragment : Fragment() { if (userPackage == null) { return -1 } - viewModel.roleLiveData.value?.let { qualifyingApplications -> - for (qualifyingApplication in qualifyingApplications) { - val qualifyingApplicationInfo = qualifyingApplication.first - val qualifyingAppUserPackage = UserPackage.from(qualifyingApplicationInfo) - if (Objects.equals(qualifyingAppUserPackage, userPackage)) { + viewModel.liveData.value?.let { applicationItems -> + for (applicationItem in applicationItems) { + val qualifyingApplicationInfo = applicationItem.applicationInfo + val qualifyingUserPackage = UserPackage.from(qualifyingApplicationInfo) + if (Objects.equals(qualifyingUserPackage, userPackage)) { return qualifyingApplicationInfo.uid } } @@ -244,12 +244,10 @@ class WearRequestRoleFragment : Fragment() { } private fun getHolderUserPackage(): UserPackage? { - viewModel.roleLiveData.value?.let { qualifyingApplications -> + viewModel.liveData.value?.let { qualifyingApplications -> for (qualifyingApplication in qualifyingApplications) { - val isHolderApplication = qualifyingApplication.second - if (isHolderApplication) { - val applicationInfo = qualifyingApplication.first - return UserPackage.from(applicationInfo) + if (qualifyingApplication.isHolderApplication) { + return UserPackage.from(qualifyingApplication.applicationInfo) } } } @@ -257,7 +255,7 @@ class WearRequestRoleFragment : Fragment() { } private fun getQualifyingApplicationCount(): Int { - return viewModel.roleLiveData.value?.size ?: -1 + return viewModel.liveData.value?.size ?: -1 } private fun setDeniedAlwaysAndFinish() { diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt index f8a1b1ee8..f95f1ee90 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleHelper.kt @@ -20,12 +20,12 @@ import android.content.Context import android.content.pm.ApplicationInfo import android.graphics.drawable.Drawable import android.os.Process -import android.util.Pair import com.android.permissioncontroller.R import com.android.permissioncontroller.permission.utils.Utils import com.android.permissioncontroller.role.UserPackage import com.android.permissioncontroller.role.model.UserDeniedManager import com.android.permissioncontroller.role.ui.RequestRoleViewModel +import com.android.permissioncontroller.role.ui.RoleApplicationItem import com.android.permissioncontroller.role.ui.wear.model.WearRequestRoleViewModel import com.android.role.controller.model.Role import java.util.Objects @@ -50,11 +50,11 @@ class WearRequestRoleHelper( UserDeniedManager.getInstance(context).isDeniedOnce(roleName, packageName) fun getNonePreference( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>, + applicationItems: List<RoleApplicationItem>, selectedPackage: UserPackage?, ): RequestRolePreference? = if (role.shouldShowNone()) { - val hasHolderApplication = hasHolderApplication(qualifyingApplications) + val hasHolderApplication = hasHolderApplication(applicationItems) RequestRolePreference( userPackage = null, label = context.getString(R.string.default_app_none), @@ -79,48 +79,47 @@ class WearRequestRoleHelper( } fun getPreferences( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>, + applicationItems: List<RoleApplicationItem>, selectedPackage: UserPackage?, ): List<RequestRolePreference> { - return qualifyingApplications - .map { qualifyingApplication -> - val userPackage = UserPackage.from(qualifyingApplication.first) + return applicationItems + .map { applicationItem -> + val userPackage = UserPackage.from(applicationItem.applicationInfo) RequestRolePreference( userPackage = userPackage, - label = Utils.getAppLabel(qualifyingApplication.first, context), + label = Utils.getAppLabel(applicationItem.applicationInfo, context), subTitle = - if (qualifyingApplication.second) { + if (applicationItem.isHolderApplication) { context.getString(R.string.request_role_current_default) } else { context.getString(role.requestDescriptionResource) }, - icon = Utils.getBadgedIcon(context, qualifyingApplication.first), + icon = Utils.getBadgedIcon(context, applicationItem.applicationInfo), checked = Objects.equals(userPackage, selectedPackage), enabled = if (!wearViewModel.dontAskAgain()) { true } else { - qualifyingApplication.second + applicationItem.isHolderApplication }, - isHolder = qualifyingApplication.second, + isHolder = applicationItem.isHolderApplication, ) } .toList() } - private fun hasHolderApplication( - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>> - ): Boolean = qualifyingApplications.map { it.second }.contains(true) + private fun hasHolderApplication(applicationItems: List<RoleApplicationItem>): Boolean = + applicationItems.map { it.isHolderApplication }.contains(true) fun shouldSetAsDefaultEnabled(enabled: Boolean): Boolean { return enabled && (wearViewModel.dontAskAgain() || !wearViewModel.isHolderChecked) } - fun initializeHolderPackage(qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>) { + fun initializeHolderPackage(applicationItems: List<RoleApplicationItem>) { wearViewModel.holderPackage = - qualifyingApplications - .find { it.second } - ?.first + applicationItems + .find { it.isHolderApplication } + ?.applicationInfo ?.let { appInfo -> UserPackage.from(appInfo) } } diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt index b4758c88b..1367f4c3c 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRequestRoleScreen.kt @@ -16,8 +16,6 @@ package com.android.permissioncontroller.role.ui.wear -import android.content.pm.ApplicationInfo -import android.util.Pair import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable @@ -31,18 +29,19 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButton -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionListFooter -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControl -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlStyle -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion import com.android.permissioncontroller.role.UserPackage import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData +import com.android.permissioncontroller.role.ui.RoleApplicationItem +import com.android.permissioncontroller.wear.permission.components.ScrollableScreen +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButton +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionListFooter +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControl +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlStyle +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion @Composable fun WearRequestRoleScreen( @@ -50,7 +49,7 @@ fun WearRequestRoleScreen( onSetAsDefault: (Boolean, UserPackage?) -> Unit, onCanceled: () -> Unit, ) { - val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList()) + val roleLiveData = helper.viewModel.liveData.observeAsState(emptyList()) val manageRoleHolderState = helper.viewModel.manageRoleHolderStateLiveData.observeAsState( ManageRoleHolderStateLiveData.STATE_WORKING @@ -102,7 +101,7 @@ internal fun WearRequestRoleContent( materialUIVersion: WearPermissionMaterialUIVersion, isLoading: Boolean, helper: WearRequestRoleHelper, - qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>, + applicationItems: List<RoleApplicationItem>, enabled: Boolean, dontAskAgain: Boolean, selectedPackage: UserPackage?, @@ -118,7 +117,7 @@ internal fun WearRequestRoleContent( showTimeText = false, isLoading = isLoading, ) { - helper.getNonePreference(qualifyingApplications, selectedPackage)?.let { pref -> + helper.getNonePreference(applicationItems, selectedPackage)?.let { pref -> item { WearPermissionToggleControl( materialUIVersion = materialUIVersion, @@ -143,7 +142,7 @@ internal fun WearRequestRoleContent( } } - for (pref in helper.getPreferences(qualifyingApplications, selectedPackage)) { + for (pref in helper.getPreferences(applicationItems, selectedPackage)) { item { WearPermissionToggleControl( materialUIVersion = materialUIVersion, diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/ui/model/PermissionUsageDetailsViewModelTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/ui/model/PermissionUsageDetailsViewModelTest.kt index eb5fdefdb..644bdfd15 100644 --- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/ui/model/PermissionUsageDetailsViewModelTest.kt +++ b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/ui/model/PermissionUsageDetailsViewModelTest.kt @@ -16,16 +16,14 @@ package com.android.permissioncontroller.permission.ui.model -import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider import androidx.arch.core.executor.testing.InstantTaskExecutorRule import androidx.lifecycle.SavedStateHandle import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.modules.utils.build.SdkLevel -import com.android.permission.flags.Flags import com.android.permissioncontroller.PermissionControllerApplication +import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModelV2 import com.google.common.truth.Truth import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -42,15 +40,14 @@ class PermissionUsageDetailsViewModelTest { @JvmField @Rule val instantTaskExecutorRule = InstantTaskExecutorRule() @Test - @RequiresFlagsEnabled(Flags.FLAG_LIVEDATA_REFACTOR_PERMISSION_TIMELINE_ENABLED) fun verifyUiStateIsGeneratedSuccessfully() { Assume.assumeTrue(SdkLevel.isAtLeastS()) lateinit var uiState: PermissionUsageDetailsUiState.Success val viewModel = - PermissionUsageDetailsViewModelV2.create( + PermissionUsageDetailsViewModel.create( PermissionControllerApplication.get(), SavedStateHandle(mapOf("show7Days" to true, "showSystem" to true)), - LOCATION_PERMISSION_GROUP + LOCATION_PERMISSION_GROUP, ) val countDownLatch = CountDownLatch(1) diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/PermissionUsageDetailsViewModelTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/PermissionUsageDetailsViewModelTest.kt index edaea9aba..4334026c3 100644 --- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/PermissionUsageDetailsViewModelTest.kt +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/ui/model/PermissionUsageDetailsViewModelTest.kt @@ -30,8 +30,8 @@ import com.android.permissioncontroller.PermissionControllerApplication import com.android.permissioncontroller.appops.data.model.v31.DiscretePackageOpsModel import com.android.permissioncontroller.appops.data.model.v31.DiscretePackageOpsModel.DiscreteOpModel import com.android.permissioncontroller.permission.domain.usecase.v31.GetPermissionGroupUsageDetailsUseCase +import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModel.PermissionUsageDetailsUiState -import com.android.permissioncontroller.permission.ui.model.v31.PermissionUsageDetailsViewModelV2 import com.android.permissioncontroller.permission.utils.LocationUtils import com.android.permissioncontroller.permission.utils.StringUtils import com.android.permissioncontroller.permission.utils.Utils @@ -67,7 +67,7 @@ import org.mockito.quality.Strictness /** * These unit tests are for new permission timeline implementation, the new view model class is - * [PermissionUsageDetailsViewModelV2] + * [PermissionUsageDetailsViewModel] */ @RunWith(AndroidJUnit4::class) class PermissionUsageDetailsViewModelTest { @@ -107,7 +107,7 @@ class PermissionUsageDetailsViewModelTest { any(), anyInt(), anyInt(), - any(Array<String>::class.java) + any(Array<String>::class.java), ) ) .thenReturn("Duration Summary") @@ -119,7 +119,7 @@ class PermissionUsageDetailsViewModelTest { systemPackageName to getPackageInfoModel( systemPackageName, - applicationFlags = ApplicationInfo.FLAG_SYSTEM + applicationFlags = ApplicationInfo.FLAG_SYSTEM, ), ) .toMutableMap() @@ -127,7 +127,7 @@ class PermissionUsageDetailsViewModelTest { packageRepository = FakePackageRepository( packageInfos, - packagesAndLabels = mapOf(testPackageName to testPackageLabel) + packagesAndLabels = mapOf(testPackageName to testPackageLabel), ) } @@ -140,9 +140,7 @@ class PermissionUsageDetailsViewModelTest { fun verifyOnlyNonSystemAppsAreShown() = runTest { val accessTimeMillis = (getCurrentTime() - TimeUnit.HOURS.toMillis(5)) val appOpEvents = - listOf( - DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, -1), - ) + listOf(DiscreteOpModel(AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, -1)) val discretePackageOps = flow { emit( listOf( @@ -176,8 +174,8 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val discretePackageOps = flow { emit( @@ -192,7 +190,7 @@ class PermissionUsageDetailsViewModelTest { getViewModel( LOCATION_PERMISSION_GROUP, discretePackageOps, - savedStateMap = mapOf("show7Days" to false, "showSystem" to true) + savedStateMap = mapOf("show7Days" to false, "showSystem" to true), ) val uiState = getPermissionUsageDetailsUiState(underTest) @@ -210,13 +208,13 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -225,7 +223,7 @@ class PermissionUsageDetailsViewModelTest { getViewModel( LOCATION_PERMISSION_GROUP, discretePackageOps, - savedStateMap = mapOf("show7Days" to false, "showSystem" to false) + savedStateMap = mapOf("show7Days" to false, "showSystem" to false), ) val uiState = getPermissionUsageDetailsUiState(underTest) @@ -240,13 +238,13 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(systemPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(systemPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -255,7 +253,7 @@ class PermissionUsageDetailsViewModelTest { getViewModel( LOCATION_PERMISSION_GROUP, discretePackageOps, - savedStateMap = mapOf("show7Days" to false, "showSystem" to false) + savedStateMap = mapOf("show7Days" to false, "showSystem" to false), ) val uiState = getPermissionUsageDetailsUiState(underTest) @@ -271,18 +269,18 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessStartWithIn24Hours, - TimeUnit.MINUTES.toMillis(5) + TimeUnit.MINUTES.toMillis(5), ), DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessStartBefore24Hours, - TimeUnit.MINUTES.toMillis(7) + TimeUnit.MINUTES.toMillis(7), ), ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -304,18 +302,18 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessTimeWithIn24Hours, - TimeUnit.MINUTES.toMillis(5) + TimeUnit.MINUTES.toMillis(5), ), DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessTimeBefore24Hours, - TimeUnit.MINUTES.toMillis(7) + TimeUnit.MINUTES.toMillis(7), ), ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -344,13 +342,13 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessTimeMillis, - TimeUnit.MINUTES.toMillis(5) - ), + TimeUnit.MINUTES.toMillis(5), + ) ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -371,13 +369,13 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_CAMERA, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } @@ -397,22 +395,16 @@ class PermissionUsageDetailsViewModelTest { whenever(application.getString(anyInt())).thenReturn("emergency attr label") val accessTimeMillis = (getCurrentTime() - TimeUnit.HOURS.toMillis(5)) val appOpEvents = - listOf( - DiscreteOpModel(AppOpsManager.OPSTR_EMERGENCY_LOCATION, accessTimeMillis, -1), - ) + listOf(DiscreteOpModel(AppOpsManager.OPSTR_EMERGENCY_LOCATION, accessTimeMillis, -1)) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } - val underTest = - getViewModel( - LOCATION_PERMISSION_GROUP, - discretePackageOps, - ) + val underTest = getViewModel(LOCATION_PERMISSION_GROUP, discretePackageOps) val uiState = getPermissionUsageDetailsUiState(underTest) assertThat(uiState.appPermissionAccessUiInfoList.size).isEqualTo(1) val timelineRow = uiState.appPermissionAccessUiInfoList.first() @@ -429,21 +421,15 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val actualData = - listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), - ) + listOf(DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents)) val discretePackageOps = MutableStateFlow(emptyList<DiscretePackageOpsModel>()) discretePackageOps.emit(emptyList()) - val underTest = - getViewModel( - LOCATION_PERMISSION_GROUP, - discretePackageOps, - ) + val underTest = getViewModel(LOCATION_PERMISSION_GROUP, discretePackageOps) val result by collectLastValue(underTest.permissionUsageDetailsUiStateFlow) var uiState = result as PermissionUsageDetailsUiState.Success assertThat(uiState.appPermissionAccessUiInfoList).isEmpty() @@ -463,22 +449,18 @@ class PermissionUsageDetailsViewModelTest { DiscreteOpModel( AppOpsManager.OPSTR_COARSE_LOCATION, accessTimeMillis, - TimeUnit.MINUTES.toMillis(1) - ), + TimeUnit.MINUTES.toMillis(1), + ) ) val discretePackageOps = flow { emit( listOf( - DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents), + DiscretePackageOpsModel(testPackageName, currentUser.identifier, appOpEvents) ) ) } - val underTest = - getViewModel( - LOCATION_PERMISSION_GROUP, - discretePackageOps, - ) + val underTest = getViewModel(LOCATION_PERMISSION_GROUP, discretePackageOps) val uiState = getPermissionUsageDetailsUiState(underTest) assertThat(uiState.show7Days).isFalse() @@ -517,20 +499,20 @@ class PermissionUsageDetailsViewModelTest { permissionGroup: String, discretePackageOps: Flow<List<DiscretePackageOpsModel>>, savedStateMap: Map<String, Boolean> = mapOf("show7Days" to false, "showSystem" to false), - pkgRepository: PackageRepository = packageRepository + pkgRepository: PackageRepository = packageRepository, ) = - PermissionUsageDetailsViewModelV2( + PermissionUsageDetailsViewModel( application, getPermissionGroupUsageDetailsUseCase(permissionGroup, discretePackageOps), SavedStateHandle(savedStateMap), permissionGroup, scope = backgroundScope, StandardTestDispatcher(testScheduler), - packageRepository = pkgRepository + packageRepository = pkgRepository, ) private fun TestScope.getPermissionUsageDetailsUiState( - viewModel: PermissionUsageDetailsViewModelV2 + viewModel: PermissionUsageDetailsViewModel ): PermissionUsageDetailsUiState.Success { val result by collectLastValue(viewModel.permissionUsageDetailsUiStateFlow) return result as PermissionUsageDetailsUiState.Success @@ -542,7 +524,7 @@ class PermissionUsageDetailsViewModelTest { permissionsFlags: List<Int> = listOf( PackageInfo.REQUESTED_PERMISSION_GRANTED, - PackageInfo.REQUESTED_PERMISSION_GRANTED + PackageInfo.REQUESTED_PERMISSION_GRANTED, ), applicationFlags: Int = 0, ) = PackageInfoModel(packageName, requestedPermissions, permissionsFlags, applicationFlags) diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt index 28f69b136..593061a83 100644 --- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt +++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/permission/utils/GrantRevokeTests.kt @@ -241,7 +241,7 @@ class GrantRevokeTests { perms: Map<String, LightPermission> = emptyMap() ): LightAppPermGroup { val pGi = LightPermGroupInfo(PERM_GROUP_NAME, TEST_PACKAGE_NAME, 0, 0, 0, false) - return LightAppPermGroup(pkgInfo, pGi, perms, false, false) + return LightAppPermGroup(pkgInfo, pGi, perms, false, false, false) } /** diff --git a/PermissionController/wear-permission-components/Android.bp b/PermissionController/wear-permission-components/Android.bp new file mode 100644 index 000000000..bdd783b60 --- /dev/null +++ b/PermissionController/wear-permission-components/Android.bp @@ -0,0 +1,67 @@ +// Copyright (C) 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_team: "trendy_team_android_permissions", + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "wear-permission-components-sources", + srcs: [ + "src/**/*.kt", + ], + visibility: ["//visibility:private"], +} + +android_library { + name: "wear-permission-components", + manifest: "AndroidManifest.xml", + sdk_version: "system_current", + min_sdk_version: "30", + target_sdk_version: "33", + srcs: [ + ":wear-permission-components-sources", + ], + resource_dirs: ["res"], + libs: [ + "androidx.annotation_annotation", + "framework-annotations-lib", + ], + static_libs: [ + "androidx.fragment_fragment", + "androidx.appcompat_appcompat", + "androidx.compose.foundation_foundation", + "androidx.compose.runtime_runtime", + "androidx.compose.runtime_runtime-livedata", + "androidx.compose.ui_ui", + "androidx.wear.compose_compose-material", + "androidx.wear.compose_compose-material3", + ], + kotlin_lang_version: "1.9", + kotlincflags: [ + "-Werror", + "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi", + "-Xjvm-default=all", + ], + installable: false, + visibility: [ + "//packages/modules:__subpackages__", + ], + apex_available: [ + "//apex_available:platform", + "com.android.permission", + "com.android.healthfitness", + ], +} diff --git a/PermissionController/wear-permission-components/AndroidManifest.xml b/PermissionController/wear-permission-components/AndroidManifest.xml new file mode 100644 index 000000000..57eca6176 --- /dev/null +++ b/PermissionController/wear-permission-components/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<manifest package="com.android.permissioncontroller.wear.permission.components"> +</manifest> diff --git a/PermissionController/res/drawable/ic_security_update_good.xml b/PermissionController/wear-permission-components/res/drawable/ic_security_update_good.xml index 59e7a67fa..59e7a67fa 100644 --- a/PermissionController/res/drawable/ic_security_update_good.xml +++ b/PermissionController/wear-permission-components/res/drawable/ic_security_update_good.xml diff --git a/PermissionController/res/values-watch/donottranslate.xml b/PermissionController/wear-permission-components/res/values/donottranslate.xml index 03038ddd1..03038ddd1 100644 --- a/PermissionController/res/values-watch/donottranslate.xml +++ b/PermissionController/wear-permission-components/res/values/donottranslate.xml diff --git a/PermissionController/wear-permission-components/res/values/overlayable.xml b/PermissionController/wear-permission-components/res/values/overlayable.xml new file mode 100644 index 000000000..94c5972f4 --- /dev/null +++ b/PermissionController/wear-permission-components/res/values/overlayable.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <overlayable name="WearPermissionControllerStyles"> + <policy type="product|system|vendor|odm|oem"> + <!--START WEAR SPECIFIC MATERIAL3 FONT FACE TOKENS--> + <item type="string" name="wear_compose_material3_arc_small_font_family" /> + <item type="string" name="wear_compose_material3_arc_medium_font_family" /> + <item type="string" name="wear_compose_material3_arc_large_font_family" /> + + <item type="string" name="wear_compose_material3_body_extra_small_font_family" /> + <item type="string" name="wear_compose_material3_body_small_font_family" /> + <item type="string" name="wear_compose_material3_body_medium_font_family" /> + <item type="string" name="wear_compose_material3_body_large_font_family" /> + + <item type="string" name="wear_compose_material3_display_small_font_family" /> + <item type="string" name="wear_compose_material3_display_medium_font_family" /> + <item type="string" name="wear_compose_material3_display_large_font_family" /> + + <item type="string" name="wear_compose_material3_label_small_font_family" /> + <item type="string" name="wear_compose_material3_label_medium_font_family" /> + <item type="string" name="wear_compose_material3_label_large_font_family" /> + + <item type="string" name="wear_compose_material3_numeral_extra_small_font_family" /> + <item type="string" name="wear_compose_material3_numeral_small_font_family" /> + <item type="string" name="wear_compose_material3_numeral_medium_font_family" /> + <item type="string" name="wear_compose_material3_numeral_large_font_family" /> + <item type="string" name="wear_compose_material3_numeral_extra_large_font_family" /> + + <item type="string" name="wear_compose_material3_title_small_font_family" /> + <item type="string" name="wear_compose_material3_title_medium_font_family" /> + <item type="string" name="wear_compose_material3_title_large_font_family" /> + <!--END WEAR SPECIFIC MATERIAL3 FONT FACE TOKENS--> + + + <!--START WEAR SPECIFIC MATERIAL3 FONT SIZE TOKENS--> + <item type="dimen" name="wear_compose_material3_arc_small_font_size" /> + <item type="dimen" name="wear_compose_material3_arc_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_arc_large_font_size" /> + + <item type="dimen" name="wear_compose_material3_body_extra_small_font_size" /> + <item type="dimen" name="wear_compose_material3_body_small_font_size" /> + <item type="dimen" name="wear_compose_material3_body_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_body_large_font_size" /> + + <item type="dimen" name="wear_compose_material3_display_small_font_size" /> + <item type="dimen" name="wear_compose_material3_display_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_display_large_font_size" /> + + <item type="dimen" name="wear_compose_material3_label_small_font_size" /> + <item type="dimen" name="wear_compose_material3_label_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_label_large_font_size" /> + + <item type="dimen" name="wear_compose_material3_numeral_extra_small_font_size" /> + <item type="dimen" name="wear_compose_material3_numeral_small_font_size" /> + <item type="dimen" name="wear_compose_material3_numeral_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_numeral_large_font_size" /> + <item type="dimen" name="wear_compose_material3_numeral_extra_large_font_size" /> + + <item type="dimen" name="wear_compose_material3_title_small_font_size" /> + <item type="dimen" name="wear_compose_material3_title_medium_font_size" /> + <item type="dimen" name="wear_compose_material3_title_large_font_size" /> + <!--END WEAR SPECIFIC MATERIAL3 FONT SIZE TOKENS--> + + <!--START WEAR SPECIFIC MATERIAL3 SHAPE TOKENS--> + <item type="dimen" name="wear_compose_material3_shape_corner_extra_small_size" /> + <item type="dimen" name="wear_compose_material3_shape_corner_small_size" /> + <item type="dimen" name="wear_compose_material3_shape_corner_medium_size" /> + <item type="dimen" name="wear_compose_material3_shape_corner_large_size" /> + <item type="dimen" name="wear_compose_material3_shape_corner_extra_large_size" /> + <!--END WEAR SPECIFIC MATERIAL3 SHAPE TOKENS--> + </policy> + </overlayable> +</resources>
\ No newline at end of file diff --git a/PermissionController/wear-permission-components/res/values/strings.xml b/PermissionController/wear-permission-components/res/values/strings.xml new file mode 100644 index 000000000..a9956ddb5 --- /dev/null +++ b/PermissionController/wear-permission-components/res/values/strings.xml @@ -0,0 +1,7 @@ +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Accessibility description indicating that a toggle control status is on. [CHAR LIMIT=NONE] --> + <string name="on">On</string> + + <!-- Accessibility description indicating that a status is off. [CHAR LIMIT=NONE] --> + <string name="off">Off</string> +</resources>
\ No newline at end of file diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AnnotatedText.kt b/PermissionController/wear-permission-components/src/wear.permission.components/AnnotatedText.kt index 07bb88e80..4d7954c5a 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AnnotatedText.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/AnnotatedText.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements +package com.android.permissioncontroller.wear.permission.components import android.text.Spanned import android.text.style.ClickableSpan @@ -32,10 +31,14 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextDecoration import androidx.wear.compose.material.MaterialTheme -import com.android.permissioncontroller.permission.ui.wear.WearUtils.capitalize +import java.util.Locale const val CLICKABLE_SPAN_TAG = "CLICKABLE_SPAN_TAG" +fun String.capitalize(): String = replaceFirstChar { + if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() +} + @Composable fun AnnotatedText( text: CharSequence, diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt b/PermissionController/wear-permission-components/src/wear.permission.components/CheckYourPhone.kt index 59376b8fa..467aae4e1 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/CheckYourPhone.kt @@ -13,26 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements +package com.android.permissioncontroller.wear.permission.components import android.content.res.Configuration +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column 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.foundation.shape.CircleShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.wear.compose.material.CircularProgressIndicator +import androidx.wear.compose.material.Icon import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.Scaffold import androidx.wear.compose.material.Text -import com.android.permissioncontroller.R private const val TOP_PADDING_SCREEN_PERCENTAGE = 0.1248f private const val BOTTOM_PADDING_SCREEN_PERCENTAGE = 0.0624f @@ -41,16 +47,12 @@ private const val TEXT_PADDING_SCREEN_PERCENTAGE = 0.0416f enum class CheckYourPhoneState { InProgress, - Success + Success, } /** * A screen to request the user to check their paired phone to proceed. It also allows a [message] * to be displayed. - * - * <img - * src="https://media.githubusercontent.com/media/google/horologist/main/docs/auth-composables/check_your_phone_screen_code.png" - * height="120" width="120"/> */ @Composable fun CheckYourPhoneScreen( @@ -60,9 +62,7 @@ fun CheckYourPhoneScreen( message: String? = null, ) { val configuration = LocalConfiguration.current - val isLarge = configuration.isLargeScreen - val topPadding = (configuration.screenHeightDp * TOP_PADDING_SCREEN_PERCENTAGE).dp val bottomPadding = (configuration.screenHeightDp * BOTTOM_PADDING_SCREEN_PERCENTAGE).dp val sidePadding = (configuration.screenHeightDp * SIDE_PADDING_SCREEN_PERCENTAGE).dp @@ -79,7 +79,7 @@ fun CheckYourPhoneScreen( bottom = bottomPadding, start = sidePadding, end = sidePadding, - ), + ) ) { Column( modifier = Modifier.fillMaxWidth().weight(1f).padding(horizontal = textPadding), @@ -104,21 +104,53 @@ fun CheckYourPhoneScreen( } } when (state) { - CheckYourPhoneState.InProgress -> - RemoteConnectionProgressIndicator( - iconRes = R.drawable.ic_security_update_good, - Modifier.align(Alignment.CenterHorizontally) - ) - CheckYourPhoneState.Success -> - RemoteConnectionSuccess( - iconRes = R.drawable.ic_security_update_good, - Modifier.align(Alignment.CenterHorizontally) - ) + CheckYourPhoneState.InProgress -> RemoteConnectionProgressIndicator() + CheckYourPhoneState.Success -> RemoteConnectionSuccess() } } } } +@Composable +private fun RemoteConnectionProgressIndicator() { + val indicatorPadding = 8.dp + val iconSize = 48.dp + val progressBarStrokeWidth = 4.dp + Box(modifier = Modifier.size(iconSize).clip(CircleShape)) { + CircularProgressIndicator( + modifier = Modifier.size(iconSize - progressBarStrokeWidth + indicatorPadding), + strokeWidth = progressBarStrokeWidth, + ) + Icon( + painter = painterResource(R.drawable.ic_security_update_good), + contentDescription = null, + modifier = + Modifier.align(Alignment.Center) + .size(iconSize - indicatorPadding - 8.dp) + .clip(CircleShape), + ) + } +} + +@Composable +private fun RemoteConnectionSuccess() { + val indicatorPadding = 8.dp + val iconSize = 48.dp + val backgroundColor = MaterialTheme.colors.onSurface + val contentColor = MaterialTheme.colors.surface + Box(modifier = Modifier.size(iconSize).clip(CircleShape).background(backgroundColor)) { + Icon( + painter = painterResource(R.drawable.ic_security_update_good), + contentDescription = null, + tint = contentColor, + modifier = + Modifier.align(Alignment.Center) + .size(iconSize - indicatorPadding - 8.dp) + .clip(CircleShape), + ) + } +} + /** Whether the device is considered large screen for layout adjustment purposes. */ internal val Configuration.isLargeScreen: Boolean get() = screenHeightDp > 224 diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt b/PermissionController/wear-permission-components/src/wear.permission.components/DrawablePainter.kt index d505a0ea4..a22fb2b96 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/DrawablePainter.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/DrawablePainter.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements +package com.android.permissioncontroller.wear.permission.components import android.graphics.drawable.Animatable import android.graphics.drawable.ColorDrawable @@ -166,5 +165,6 @@ private val Drawable.intrinsicSize: Size internal object EmptyPainter : Painter() { override val intrinsicSize: Size get() = Size.Unspecified + override fun DrawScope.onDraw() {} } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt b/PermissionController/wear-permission-components/src/wear.permission.components/ScrollableScreen.kt index bfa46ae55..db3711670 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/ScrollableScreen.kt @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements +package com.android.permissioncontroller.wear.permission.components import android.app.Activity import android.content.Context import android.content.ContextWrapper +import androidx.compose.foundation.layout.BoxScope import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -27,12 +27,13 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.fragment.app.FragmentActivity +import androidx.wear.compose.foundation.ExpandableState import androidx.wear.compose.foundation.SwipeToDismissValue import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState import androidx.wear.compose.material.SwipeToDismissBox -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionScaffold -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionScaffold +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion /** * Screen that contains a list of items defined using the [content] parameter, adds the time text @@ -43,6 +44,7 @@ import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionM @Composable fun ScrollableScreen( materialUIVersion: WearPermissionMaterialUIVersion = ResourceHelper.materialUIVersionInSettings, + asScalingList: Boolean = false, showTimeText: Boolean = true, title: String? = null, subtitle: CharSequence? = null, @@ -74,6 +76,7 @@ fun ScrollableScreen( SwipeToDismissBox(state = state) { isBackground -> WearPermissionScaffold( materialUIVersion, + asScalingList, showTimeText, title, subtitle, @@ -87,6 +90,7 @@ fun ScrollableScreen( } else { WearPermissionScaffold( materialUIVersion, + asScalingList, showTimeText, title, subtitle, @@ -99,7 +103,7 @@ fun ScrollableScreen( } } -internal fun dismiss(activity: Activity) { +fun dismiss(activity: Activity) { if (activity is FragmentActivity) { if (!activity.supportFragmentManager.popBackStackImmediate()) { activity.finish() @@ -119,7 +123,7 @@ internal fun getBackStackEntryCount(activity: Activity): Int { } } -internal fun Context.findActivity(): Activity { +fun Context.findActivity(): Activity { var context = this while (context is ContextWrapper) { if (context is Activity) return context @@ -130,4 +134,11 @@ internal fun Context.findActivity(): Activity { interface ListScopeWrapper { fun item(key: Any? = null, contentType: Any? = null, content: @Composable () -> Unit) + + fun expandableItems( + state: ExpandableState, + count: Int, + key: ((index: Int) -> Any)? = null, + itemContent: @Composable BoxScope.(index: Int) -> Unit, + ) } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/AlertDialog.kt index a49d8822e..652adfc07 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/AlertDialog.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/AlertDialog.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable @@ -36,11 +36,11 @@ import androidx.wear.compose.material.LocalTextStyle import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.Text import androidx.wear.compose.material.dialog.Dialog -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnDefaults -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.rememberColumnState -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnDefaults +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnState +import com.android.permissioncontroller.wear.permission.components.material2.layout.rememberColumnState +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder /** * This component is an alternative to [AlertContent], providing the following: diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Chip.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt index 15542ec20..f0dab21ec 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Chip.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import android.graphics.drawable.Drawable import androidx.annotation.StringRes @@ -46,7 +46,7 @@ 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.permission.ui.wear.elements.rememberDrawablePainter +import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter /** * This component is an alternative to [Chip], providing the following: diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Icon.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Icon.kt index 3cfac7eef..dfed0b196 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Icon.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Icon.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import android.graphics.drawable.Drawable import androidx.annotation.DrawableRes @@ -29,14 +29,14 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.wear.compose.material.Icon import androidx.wear.compose.material.LocalContentAlpha import androidx.wear.compose.material.LocalContentColor -import com.android.permissioncontroller.permission.ui.wear.elements.rememberDrawablePainter +import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter /** * This component is an alternative to [Icon], providing the following: * - a convenient way of setting the icon to be mirrored in RTL mode; */ @Composable -public fun Icon( +fun Icon( imageVector: ImageVector, contentDescription: String?, modifier: Modifier = Modifier, @@ -58,7 +58,7 @@ public fun Icon( * - a convenient way of setting the icon to be mirrored in RTL mode; */ @Composable -public fun Icon( +fun Icon( @DrawableRes id: Int, contentDescription: String?, modifier: Modifier = Modifier, @@ -122,7 +122,7 @@ fun Icon( } } -public enum class IconRtlMode { +enum class IconRtlMode { Default, Mirrored, } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ListFooter.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListFooter.kt index 4f6d47faf..ac603d492 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ListFooter.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListFooter.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ListHeader.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt index 2d3eb0d52..7dc26179d 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ListHeader.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ResponsiveDialog.kt index 4cb3ab615..64597e23d 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ResponsiveDialog.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ResponsiveDialog.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement.spacedBy @@ -44,14 +44,14 @@ import androidx.wear.compose.material.LocalTextStyle import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.PositionIndicator import androidx.wear.compose.material.Scaffold -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumn -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnDefaults.responsive -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.rememberColumnState -import com.android.permissioncontroller.permission.ui.wear.elements.material3.DialogButtonContent -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionIconBuilder -import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertConfirmIcon -import com.android.permissioncontroller.permission.ui.wear.elements.material3.defaultAlertDismissIcon +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumn +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnDefaults.responsive +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnState +import com.android.permissioncontroller.wear.permission.components.material2.layout.rememberColumnState +import com.android.permissioncontroller.wear.permission.components.material3.DialogButtonContent +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionIconBuilder +import com.android.permissioncontroller.wear.permission.components.material3.defaultAlertConfirmIcon +import com.android.permissioncontroller.wear.permission.components.material3.defaultAlertDismissIcon @Composable fun ResponsiveDialogContent( diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ToggleChip.kt index bfb5d114d..de8e0542d 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/ToggleChip.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ToggleChip.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.BoxScope @@ -44,8 +43,8 @@ import androidx.wear.compose.material.ToggleChip import androidx.wear.compose.material.ToggleChipColors import androidx.wear.compose.material.ToggleChipDefaults import androidx.wear.compose.material.contentColorFor -import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionToggleControlType +import com.android.permissioncontroller.wear.permission.components.R +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionToggleControlType /** * This component is an alternative to [ToggleChip], providing the following: diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Wear2Scaffold.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Wear2Scaffold.kt index 866b7f012..b5ba5b71e 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/Wear2Scaffold.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Wear2Scaffold.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material2 +package com.android.permissioncontroller.wear.permission.components.material2 import android.graphics.drawable.Drawable import androidx.compose.foundation.Image @@ -54,9 +53,9 @@ import androidx.wear.compose.material.TimeText import androidx.wear.compose.material.Vignette import androidx.wear.compose.material.VignettePosition import androidx.wear.compose.material.scrollAway -import com.android.permissioncontroller.permission.ui.wear.elements.AnnotatedText -import com.android.permissioncontroller.permission.ui.wear.elements.rememberDrawablePainter -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.AnnotatedText +import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme /** * This component is wrapper on material 2 scaffold component. It helps with time text, scroll diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/layout/ScalingLazyColumnDefaults.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/layout/ScalingLazyColumnDefaults.kt index c06fdaf14..f6fe5233c 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/layout/ScalingLazyColumnDefaults.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/layout/ScalingLazyColumnDefaults.kt @@ -16,7 +16,7 @@ @file:Suppress("ObjectLiteralToLambda") -package com.android.permissioncontroller.permission.ui.wear.elements.material2.layout +package com.android.permissioncontroller.wear.permission.components.material2.layout import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -33,7 +33,7 @@ import androidx.wear.compose.foundation.lazy.ScalingLazyColumnDefaults import androidx.wear.compose.foundation.lazy.ScalingLazyListAnchorType import androidx.wear.compose.foundation.lazy.ScalingParams import androidx.wear.compose.material.ChipDefaults -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState.RotaryMode +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnState.RotaryMode import kotlin.math.sqrt // This file's content is copied from ScalingLazyColumnDefaults.kt from Horologist (go/horologist), diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/layout/ScalingLazyColumnState.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/layout/ScalingLazyColumnState.kt index 0e669f6ff..c20b23aa3 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material2/layout/ScalingLazyColumnState.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/layout/ScalingLazyColumnState.kt @@ -17,7 +17,7 @@ @file:Suppress("ObjectLiteralToLambda") @file:OptIn(ExperimentalWearFoundationApi::class) -package com.android.permissioncontroller.permission.ui.wear.elements.material2.layout +package com.android.permissioncontroller.wear.permission.components.material2.layout import androidx.compose.foundation.MutatePriority import androidx.compose.foundation.gestures.FlingBehavior @@ -42,8 +42,8 @@ import androidx.wear.compose.foundation.lazy.ScalingLazyListAnchorType import androidx.wear.compose.foundation.lazy.ScalingLazyListScope import androidx.wear.compose.foundation.lazy.ScalingLazyListState import androidx.wear.compose.foundation.lazy.ScalingParams -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnDefaults.responsiveScalingParams -import com.android.permissioncontroller.permission.ui.wear.elements.material2.layout.ScalingLazyColumnState.RotaryMode +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnDefaults.responsiveScalingParams +import com.android.permissioncontroller.wear.permission.components.material2.layout.ScalingLazyColumnState.RotaryMode // This file is a copy of ScalingLazyColumnState.kt from Horologist (go/horologist), // remove it once after wear compose supports large screen dialogs. diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt index 9a89e0809..1a7524e7c 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButton.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues @@ -33,9 +33,9 @@ import androidx.wear.compose.material3.ButtonDefaults import androidx.wear.compose.material3.LocalTextConfiguration import androidx.wear.compose.material3.LocalTextStyle import androidx.wear.compose.material3.Text -import com.android.permissioncontroller.permission.ui.wear.elements.material2.Chip -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.material2.Chip +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion /** * This component is wrapper on material Button component diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButtonStyle.kt index 36d3f9f33..114bcd4bc 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionButtonStyle.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButtonStyle.kt @@ -13,20 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.runtime.Composable import androidx.wear.compose.material.ChipColors import androidx.wear.compose.material.ChipDefaults import androidx.wear.compose.material3.ButtonColors import androidx.wear.compose.material3.ButtonDefaults -import com.android.permissioncontroller.permission.ui.wear.elements.material2.chipDefaultColors -import com.android.permissioncontroller.permission.ui.wear.elements.material2.chipDisabledColors -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.DisabledLike -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.Primary -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.Secondary -import com.android.permissioncontroller.permission.ui.wear.elements.material3.WearPermissionButtonStyle.Transparent +import com.android.permissioncontroller.wear.permission.components.material2.chipDefaultColors +import com.android.permissioncontroller.wear.permission.components.material2.chipDisabledColors +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle.DisabledLike +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle.Primary +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle.Secondary +import com.android.permissioncontroller.wear.permission.components.material3.WearPermissionButtonStyle.Transparent /** * This component is wrapper on material control colors, It applies the right colors based material diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionConfirmationDialog.kt index 0e1bf1fbe..4ef6e8a72 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionConfirmationDialog.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionConfirmationDialog.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.size @@ -25,8 +25,8 @@ import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState import androidx.wear.compose.material3.AlertDialog as Material3AlertDialog import androidx.wear.compose.material3.AlertDialogDefaults import androidx.wear.compose.material3.Text -import com.android.permissioncontroller.permission.ui.wear.elements.material2.AlertDialog -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.material2.AlertDialog +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion data class DialogButtonContent( val icon: WearPermissionIconBuilder? = null, diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionIconBuilder.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionIconBuilder.kt index 52674b50d..e5e51af66 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionIconBuilder.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionIconBuilder.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import android.graphics.drawable.Drawable import androidx.compose.foundation.layout.size @@ -29,7 +29,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.IconButtonDefaults -import com.android.permissioncontroller.permission.ui.wear.elements.rememberDrawablePainter +import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter /** * This class simplifies the construction of icons with various attributes like resource type, diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListFooter.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionListFooter.kt index 33f9cb41f..90ee09bab 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListFooter.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionListFooter.kt @@ -13,17 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.PaddingValues import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.unit.dp import androidx.wear.compose.material3.ButtonDefaults -import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListFooter -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.material2.ListFooter +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion /** This component is creates a transparent styled button to use as a list footer. */ @Composable diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionListSubHeader.kt index ddcd93326..2ed6e532f 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionListSubHeader.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionListSubHeader.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.padding @@ -23,9 +23,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.unit.dp import androidx.wear.compose.material3.ListSubHeader -import com.android.permissioncontroller.permission.ui.wear.elements.material2.ListSubheader -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.material2.ListSubheader +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion /* This component is simplified wrapper over ListSubHeader with quick padding adjustments diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionScaffold.kt index 35bdf583e..5110a5812 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffold.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionScaffold.kt @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import android.graphics.drawable.Drawable import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.ScrollableState import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues @@ -37,11 +38,16 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.Hyphens import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.wear.compose.foundation.ExpandableState import androidx.wear.compose.foundation.ScrollInfoProvider +import androidx.wear.compose.foundation.expandableItems +import androidx.wear.compose.foundation.lazy.ScalingLazyColumn import androidx.wear.compose.foundation.lazy.ScalingLazyListScope +import androidx.wear.compose.foundation.lazy.ScalingLazyListState import androidx.wear.compose.foundation.lazy.TransformingLazyColumn import androidx.wear.compose.foundation.lazy.TransformingLazyColumnScope import androidx.wear.compose.foundation.lazy.TransformingLazyColumnState +import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState import androidx.wear.compose.material3.AppScaffold import androidx.wear.compose.material3.CircularProgressIndicator @@ -53,14 +59,14 @@ import androidx.wear.compose.material3.ScrollIndicator import androidx.wear.compose.material3.Text import androidx.wear.compose.material3.TimeText import androidx.wear.compose.material3.lazy.scrollTransform -import com.android.permissioncontroller.permission.ui.wear.elements.AnnotatedText -import com.android.permissioncontroller.permission.ui.wear.elements.ListScopeWrapper -import com.android.permissioncontroller.permission.ui.wear.elements.material2.Wear2Scaffold -import com.android.permissioncontroller.permission.ui.wear.elements.rememberDrawablePainter -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion.MATERIAL2_5 -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionTheme +import com.android.permissioncontroller.wear.permission.components.AnnotatedText +import com.android.permissioncontroller.wear.permission.components.ListScopeWrapper +import com.android.permissioncontroller.wear.permission.components.material2.Wear2Scaffold +import com.android.permissioncontroller.wear.permission.components.rememberDrawablePainter +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion.MATERIAL2_5 +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionTheme private class TransformingScopeConverter(private val scope: TransformingLazyColumnScope) : ListScopeWrapper { @@ -68,12 +74,30 @@ private class TransformingScopeConverter(private val scope: TransformingLazyColu // TODO:https://buganizer.corp.google.com/issues/389093588. scope.item { Box(modifier = Modifier.scrollTransform(this)) { content() } } } + + override fun expandableItems( + state: ExpandableState, + count: Int, + key: ((Int) -> Any)?, + itemContent: @Composable (BoxScope.(Int) -> Unit), + ) { + throw Exception("Expandable Items are not implemented on TLC Yet. Use SLC.") + } } private class ScalingScopeConverter(private val scope: ScalingLazyListScope) : ListScopeWrapper { override fun item(key: Any?, contentType: Any?, content: @Composable () -> Unit) { scope.item { content() } } + + override fun expandableItems( + state: ExpandableState, + count: Int, + key: ((Int) -> Any)?, + itemContent: @Composable (BoxScope.(Int) -> Unit), + ) { + scope.expandableItems(state, count, key, itemContent) + } } /** @@ -81,8 +105,9 @@ private class ScalingScopeConverter(private val scope: ScalingLazyListScope) : L * indicator and standard list elements like title, icon and subtitle. */ @Composable -internal fun WearPermissionScaffold( +fun WearPermissionScaffold( materialUIVersion: WearPermissionMaterialUIVersion = ResourceHelper.materialUIVersionInSettings, + asScalingList: Boolean = false, showTimeText: Boolean, title: String?, subtitle: CharSequence?, @@ -106,59 +131,61 @@ internal fun WearPermissionScaffold( ) } else { WearPermissionScaffoldInternal( - showTimeText, - title, - subtitle, - image, - isLoading, - { content.invoke(TransformingScopeConverter(this)) }, - titleTestTag, - subtitleTestTag, + asScalingList = asScalingList, + showTimeText = showTimeText, + title = title, + subtitle = subtitle, + image = image, + isLoading = isLoading, + content = content, + titleTestTag = titleTestTag, + subtitleTestTag = subtitleTestTag, ) } } @Composable private fun WearPermissionScaffoldInternal( + asScalingList: Boolean = false, showTimeText: Boolean, title: String?, subtitle: CharSequence?, image: Any?, isLoading: Boolean, - content: TransformingLazyColumnScope.() -> Unit, + content: ListScopeWrapper.() -> Unit, titleTestTag: String? = null, subtitleTestTag: String? = null, ) { - val screenWidth = LocalConfiguration.current.screenWidthDp - val screenHeight = LocalConfiguration.current.screenHeightDp - val paddingDefaults = - WearPermissionScaffoldPaddingDefaults( - screenWidth = screenWidth, - screenHeight = screenHeight, - ) - val columnState = rememberTransformingLazyColumnState() + + val scalingListState = rememberScalingLazyListState() + val transformingLazyColumnState = rememberTransformingLazyColumnState() + val listState = if (asScalingList) scalingListState else transformingLazyColumnState + val scrollInfoProvider = + if (asScalingList) ScrollInfoProvider(scalingListState) + else ScrollInfoProvider(transformingLazyColumnState) + val positionIndicator = + if (asScalingList) wearPermissionScrollIndicator(!isLoading, scalingListState) + else wearPermissionScrollIndicator(!isLoading, transformingLazyColumnState) + WearPermissionTheme(version = WearPermissionMaterialUIVersion.MATERIAL3) { AppScaffold(timeText = wearPermissionTimeText(showTimeText && !isLoading)) { ScreenScaffold( - scrollInfoProvider = ScrollInfoProvider(columnState), - scrollIndicator = wearPermissionScrollIndicator(!isLoading, columnState), + scrollInfoProvider = scrollInfoProvider, + scrollIndicator = positionIndicator, ) { Box(modifier = Modifier.fillMaxSize()) { if (isLoading) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } else { - ScrollingView( - contentPadding = paddingDefaults.scrollContentPadding, - columnState = columnState, - icon = painterFromImage(image), + LazyColumnView( + asScalingList = asScalingList, + listState = listState, title = title, - titleTestTag = titleTestTag, - titlePaddingValues = - paddingDefaults.titlePaddingValues(subtitle == null), subtitle = subtitle, - subtitleTestTag = subtitleTestTag, - subTitlePaddingValues = paddingDefaults.subTitlePaddingValues, + image = image, content = content, + titleTestTag = titleTestTag, + subtitleTestTag = subtitleTestTag, ) } } @@ -168,37 +195,60 @@ private fun WearPermissionScaffoldInternal( } @Composable -private fun BoxScope.ScrollingView( - contentPadding: PaddingValues, - columnState: TransformingLazyColumnState, - icon: Painter?, +private fun BoxScope.LazyColumnView( + asScalingList: Boolean = false, + listState: ScrollableState, title: String?, - titleTestTag: String?, subtitle: CharSequence?, - subtitleTestTag: String?, - titlePaddingValues: PaddingValues, - subTitlePaddingValues: PaddingValues, - content: TransformingLazyColumnScope.() -> Unit, + image: Any?, + content: ListScopeWrapper.() -> Unit, + titleTestTag: String? = null, + subtitleTestTag: String? = null, ) { - TransformingLazyColumn( - contentPadding = contentPadding, - state = columnState, - modifier = Modifier.background(MaterialTheme.colorScheme.background), - ) { - with(TransformingScopeConverter(this)) { - iconItem(icon, Modifier.size(IconButtonDefaults.LargeIconSize)) + val screenWidth = LocalConfiguration.current.screenWidthDp + val screenHeight = LocalConfiguration.current.screenHeightDp + val paddingDefaults = + WearPermissionScaffoldPaddingDefaults( + screenWidth = screenWidth, + screenHeight = screenHeight, + ) + val painterImage = image?.let { painterFromImage(image = image) } + + fun BoxScope.scrollingViewContent(scopeWrapper: ListScopeWrapper) { + with(scopeWrapper) { + iconItem( + painter = painterImage, + modifier = Modifier.size(IconButtonDefaults.LargeIconSize), + ) titleItem( text = title, testTag = titleTestTag, - contentPaddingValues = titlePaddingValues, + contentPaddingValues = paddingDefaults.titlePaddingValues(subtitle == null), ) subtitleItem( text = subtitle, testTag = subtitleTestTag, - modifier = Modifier.align(Alignment.Center).padding(subTitlePaddingValues), + modifier = + Modifier.align(Alignment.Center).padding(paddingDefaults.subTitlePaddingValues), ) + content() } - content() + } + + if (asScalingList) { + ScalingLazyColumn( + contentPadding = paddingDefaults.scrollContentPadding, + state = listState as ScalingLazyListState, + modifier = Modifier.background(MaterialTheme.colorScheme.background), + content = { scrollingViewContent(ScalingScopeConverter(this)) }, + ) + } else { + TransformingLazyColumn( + contentPadding = paddingDefaults.scrollContentPadding, + state = listState as TransformingLazyColumnState, + modifier = Modifier.background(MaterialTheme.colorScheme.background), + content = { scrollingViewContent(TransformingScopeConverter(this)) }, + ) } } @@ -221,6 +271,17 @@ private fun wearPermissionScrollIndicator( } } +private fun wearPermissionScrollIndicator( + showIndicator: Boolean, + columnState: ScalingLazyListState, +): @Composable (BoxScope.() -> Unit)? { + return if (showIndicator) { + { ScrollIndicator(modifier = Modifier.align(Alignment.CenterEnd), state = columnState) } + } else { + null + } +} + @Composable private fun painterFromImage(image: Any?): Painter? { return when (image) { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionScaffoldPaddingDefaults.kt index 14eaec4bf..93a25279c 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionScaffoldPaddingDefaults.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionScaffoldPaddingDefaults.kt @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.PaddingValues import androidx.compose.ui.unit.dp diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionToggleControl.kt index d37d17a84..1dfb90682 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControl.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionToggleControl.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.RowScope @@ -28,10 +28,10 @@ import androidx.wear.compose.material3.LocalTextConfiguration import androidx.wear.compose.material3.RadioButton import androidx.wear.compose.material3.SwitchButton import androidx.wear.compose.material3.Text -import com.android.permissioncontroller.R -import com.android.permissioncontroller.permission.ui.wear.elements.material2.ToggleChip -import com.android.permissioncontroller.permission.ui.wear.theme.ResourceHelper -import com.android.permissioncontroller.permission.ui.wear.theme.WearPermissionMaterialUIVersion +import com.android.permissioncontroller.wear.permission.components.R +import com.android.permissioncontroller.wear.permission.components.material2.ToggleChip +import com.android.permissioncontroller.wear.permission.components.theme.ResourceHelper +import com.android.permissioncontroller.wear.permission.components.theme.WearPermissionMaterialUIVersion /** Defines various toggle control types. */ enum class WearPermissionToggleControlType { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControlStyle.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionToggleControlStyle.kt index 048a06861..26a0ea0ef 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/material3/WearPermissionToggleControlStyle.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionToggleControlStyle.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.elements.material3 +package com.android.permissioncontroller.wear.permission.components.material3 import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color @@ -25,8 +25,8 @@ import androidx.wear.compose.material3.RadioButtonColors import androidx.wear.compose.material3.RadioButtonDefaults.radioButtonColors import androidx.wear.compose.material3.SwitchButtonColors import androidx.wear.compose.material3.SwitchButtonDefaults.switchButtonColors -import com.android.permissioncontroller.permission.ui.wear.elements.material2.toggleChipBackgroundColors -import com.android.permissioncontroller.permission.ui.wear.elements.material2.toggleChipDisabledColors +import com.android.permissioncontroller.wear.permission.components.material2.toggleChipBackgroundColors +import com.android.permissioncontroller.wear.permission.components.material2.toggleChipDisabledColors /** * Defines toggle control styles, It helps in setting the right colors scheme to a toggle control. diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/ResourceHelper.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/ResourceHelper.kt index 2a40a625f..010d66a30 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/ResourceHelper.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/ResourceHelper.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import android.content.Context import android.os.SystemProperties @@ -23,7 +23,7 @@ import androidx.annotation.DoNotInline import androidx.annotation.StringRes import androidx.compose.ui.graphics.Color -internal object ResourceHelper { +object ResourceHelper { private const val MATERIAL3_ENABLED_SYSPROP = "persist.cw_build.bluechip.enabled" @@ -61,7 +61,7 @@ internal object ResourceHelper { return try { val colorInt = context.resources.getColor(id, context.theme) Color(colorInt) - } catch (e: Exception) { + } catch (_: Exception) { null } } @@ -70,7 +70,7 @@ internal object ResourceHelper { fun getString(context: Context, @StringRes id: Int): String? { return try { context.resources.getString(id) - } catch (e: Exception) { + } catch (_: Exception) { null } } @@ -79,7 +79,7 @@ internal object ResourceHelper { fun getDimen(context: Context, @DimenRes id: Int): Float? { return try { context.resources.getDimension(id) / context.resources.displayMetrics.density - } catch (e: Exception) { + } catch (_: Exception) { null } } diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3ColorScheme.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3ColorScheme.kt index 7ac6c8114..41e8fd975 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3ColorScheme.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3ColorScheme.kt @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import android.content.Context import android.os.Build import androidx.annotation.ColorRes import androidx.annotation.RequiresApi import androidx.compose.ui.graphics.Color +import androidx.wear.compose.material.Colors import androidx.wear.compose.material3.ColorScheme /** @@ -29,6 +30,24 @@ import androidx.wear.compose.material3.ColorScheme */ internal object WearComposeMaterial3ColorScheme { + fun legacyColorScheme(): ColorScheme { + return Colors().run { + ColorScheme( + background = background, + onBackground = onBackground, + onPrimaryContainer = primary, + primaryDim = primaryVariant, + onPrimary = onPrimary, + tertiary = secondary, // Best-Fit Mapping: Refer WearMaterialBridgedTheme. + tertiaryDim = secondaryVariant, + onTertiary = onSecondary, + surfaceContainer = surface, + onSurface = onSurface, + onSurfaceVariant = onSurfaceVariant, + ) + } + } + @RequiresApi(Build.VERSION_CODES.S) fun tonalColorScheme(context: Context): ColorScheme { val tonalPalette = dynamicTonalPalette(context) diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3Shapes.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3Shapes.kt index f81022842..89851d60e 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3Shapes.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3Shapes.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import android.content.Context import androidx.annotation.DimenRes @@ -21,7 +21,7 @@ import androidx.compose.foundation.shape.CornerBasedShape import androidx.compose.foundation.shape.CornerSize import androidx.compose.ui.unit.dp import androidx.wear.compose.material3.Shapes -import com.android.permissioncontroller.R +import com.android.permissioncontroller.wear.permission.components.R // TODO(b/324928718): Use system defined symbols. internal object WearComposeMaterial3Shapes { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3TypeScaleTokens.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3TypeScaleTokens.kt index a4ec9ee1d..df5057472 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3TypeScaleTokens.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3TypeScaleTokens.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme /* * These values are retrieved from https://carbon.googleplex.com/wear-m3/pages and diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3Typography.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3Typography.kt index ceae526a7..e44a24981 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3Typography.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3Typography.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import android.content.Context import androidx.annotation.DimenRes @@ -25,7 +25,7 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontVariation import androidx.compose.ui.unit.sp import androidx.wear.compose.material3.Typography -import com.android.permissioncontroller.R +import com.android.permissioncontroller.wear.permission.components.R internal object WearComposeMaterial3Typography { diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3VariableFontTokens.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3VariableFontTokens.kt index 1b42a3b05..644a1b754 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearComposeMaterial3VariableFontTokens.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearComposeMaterial3VariableFontTokens.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import androidx.compose.ui.text.font.FontVariation diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearMaterialBridgedLegacyTheme.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearMaterialBridgedLegacyTheme.kt index 160dc2e93..51ae16477 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearMaterialBridgedLegacyTheme.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearMaterialBridgedLegacyTheme.kt @@ -13,10 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme -import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.ui.unit.sp import androidx.wear.compose.material.Colors import androidx.wear.compose.material.Shapes @@ -29,10 +27,8 @@ import androidx.wear.compose.material.Typography * However to avoid maintaining two sets of resources for overlays, this class construct 2.5 theme * from 3.0 */ -@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) internal class WearMaterialBridgedLegacyTheme private constructor(newTheme: WearOverlayableMaterial3Theme) { - val colors = newTheme.colorScheme.run { Colors( diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearOverlayableMaterial3Theme.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearOverlayableMaterial3Theme.kt index 8aeb5f74d..f6bf56f47 100644 --- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/theme/WearOverlayableMaterial3Theme.kt +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearOverlayableMaterial3Theme.kt @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.permissioncontroller.permission.ui.wear.theme +package com.android.permissioncontroller.wear.permission.components.theme import android.content.Context import android.os.Build -import androidx.annotation.RequiresApi /** * Theme wrapper providing Material 3 styling while maintaining compatibility with Runtime Resource @@ -26,13 +25,18 @@ import androidx.annotation.RequiresApi * Uses the tonal palette from the previous Material Design version until dynamic color tokens are * available in SDK 36. */ -@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) internal class WearOverlayableMaterial3Theme(context: Context) { val colorScheme = - if (Build.VERSION.SDK_INT >= 36) { - WearComposeMaterial3ColorScheme.dynamicColorScheme(context) - } else { - WearComposeMaterial3ColorScheme.tonalColorScheme(context) + when { + Build.VERSION.SDK_INT >= 36 -> { + WearComposeMaterial3ColorScheme.dynamicColorScheme(context) + } + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + WearComposeMaterial3ColorScheme.tonalColorScheme(context) + } + else -> { + WearComposeMaterial3ColorScheme.legacyColorScheme() + } } val typography = WearComposeMaterial3Typography.dynamicTypography(context) diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTheme.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTheme.kt new file mode 100644 index 000000000..b1c87108c --- /dev/null +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTheme.kt @@ -0,0 +1,59 @@ +/* + * 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.wear.permission.components.theme + +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.wear.compose.material.MaterialTheme +import androidx.wear.compose.material3.MaterialTheme as Material3Theme + +/** This enum is used to specify the material version used for a specific screen */ +enum class WearPermissionMaterialUIVersion { + MATERIAL2_5, + MATERIAL3, +} + +/** An overlay-able compose theme supporting both material2.5 and 3. */ +@Composable +fun WearPermissionTheme( + version: WearPermissionMaterialUIVersion = ResourceHelper.materialUIVersionInSettings, + content: @Composable () -> Unit, +) { + WearOverlayableMaterial3Theme(LocalContext.current).run { + when (version) { + WearPermissionMaterialUIVersion.MATERIAL3 -> + Material3Theme( + colorScheme = colorScheme, + typography = typography, + shapes = shapes, + content = content, + ) + // Material2_5 UI controls are still being used in the screen, + // To avoid having two set of overlay resources, we will use material3 overlay resources + // to + // support material2_5 UI controls as well. + WearPermissionMaterialUIVersion.MATERIAL2_5 -> + WearMaterialBridgedLegacyTheme.createFrom(this).run { + MaterialTheme( + colors = colors, + typography = typography, + shapes = shapes, + content = content, + ) + } + } + } +} diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTonalPalette.kt b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTonalPalette.kt new file mode 100644 index 000000000..72aa3e487 --- /dev/null +++ b/PermissionController/wear-permission-components/src/wear.permission.components/theme/WearPermissionTonalPalette.kt @@ -0,0 +1,216 @@ +@file:Suppress("unused") + +/* + * 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.wear.permission.components.theme + +import android.content.Context +import android.os.Build +import androidx.annotation.ColorRes +import androidx.annotation.DoNotInline +import androidx.annotation.RequiresApi +import androidx.compose.ui.graphics.Color + +/** + * Tonal Palette structure in Material. + * + * A tonal palette is comprised of 5 tonal ranges. Each tonal range includes the 13 stops, or tonal + * swatches. + * + * Tonal range names are: + * - Neutral (N) + * - Neutral variant (NV) + * - Primary (P) + * - Secondary (S) + * - Tertiary (T) + */ +internal class WearPermissionTonalPalette( + // The neutral tonal range. + val neutral100: Color, + val neutral99: Color, + val neutral95: Color, + val neutral90: Color, + val neutral80: Color, + val neutral70: Color, + val neutral60: Color, + val neutral50: Color, + val neutral40: Color, + val neutral30: Color, + val neutral20: Color, + val neutral10: Color, + val neutral0: Color, + + // The neutral variant tonal range, sometimes called "neutral 2" + val neutralVariant100: Color, + val neutralVariant99: Color, + val neutralVariant95: Color, + val neutralVariant90: Color, + val neutralVariant80: Color, + val neutralVariant70: Color, + val neutralVariant60: Color, + val neutralVariant50: Color, + val neutralVariant40: Color, + val neutralVariant30: Color, + val neutralVariant20: Color, + val neutralVariant10: Color, + val neutralVariant0: Color, + + // The primary tonal range, also known as accent 1 + val primary100: Color, + val primary99: Color, + val primary95: Color, + val primary90: Color, + val primary80: Color, + val primary70: Color, + val primary60: Color, + val primary50: Color, + val primary40: Color, + val primary30: Color, + val primary20: Color, + val primary10: Color, + val primary0: Color, + + // The Secondary tonal range, also know as accent 2 + val secondary100: Color, + val secondary99: Color, + val secondary95: Color, + val secondary90: Color, + val secondary80: Color, + val secondary70: Color, + val secondary60: Color, + val secondary50: Color, + val secondary40: Color, + val secondary30: Color, + val secondary20: Color, + val secondary10: Color, + val secondary0: Color, + + // The tertiary tonal range, also known as accent 3 + val tertiary100: Color, + val tertiary99: Color, + val tertiary95: Color, + val tertiary90: Color, + val tertiary80: Color, + val tertiary70: Color, + val tertiary60: Color, + val tertiary50: Color, + val tertiary40: Color, + val tertiary30: Color, + val tertiary20: Color, + val tertiary10: Color, + val tertiary0: Color, +) + +/** Dynamic colors for wear compose material to support resource overlay. */ +@RequiresApi(Build.VERSION_CODES.S) +internal fun dynamicTonalPalette(context: Context) = + WearPermissionTonalPalette( + // The neutral tonal range from the generated dynamic color palette. + neutral100 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_0), + neutral99 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_10), + neutral95 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_50), + neutral90 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_100), + neutral80 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_200), + neutral70 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_300), + neutral60 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_400), + neutral50 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_500), + neutral40 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_600), + neutral30 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_700), + neutral20 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_800), + neutral10 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_900), + neutral0 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_1000), + + // The neutral variant tonal range, sometimes called "neutral 2", from the + // generated dynamic color palette. + neutralVariant100 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_0), + neutralVariant99 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_10), + neutralVariant95 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_50), + neutralVariant90 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_100), + neutralVariant80 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_200), + neutralVariant70 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_300), + neutralVariant60 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_400), + neutralVariant50 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_500), + neutralVariant40 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600), + neutralVariant30 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_700), + neutralVariant20 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_800), + neutralVariant10 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_900), + neutralVariant0 = + ColorResourceHelper.getColor(context, android.R.color.system_neutral2_1000), + + // The primary tonal range from the generated dynamic color palette. + primary100 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_0), + primary99 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_10), + primary95 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_50), + primary90 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_100), + primary80 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_200), + primary70 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_300), + primary60 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_400), + primary50 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_500), + primary40 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_600), + primary30 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_700), + primary20 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_800), + primary10 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_900), + primary0 = ColorResourceHelper.getColor(context, android.R.color.system_accent1_1000), + + // The secondary tonal range from the generated dynamic color palette. + secondary100 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_0), + secondary99 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_10), + secondary95 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_50), + secondary90 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_100), + secondary80 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_200), + secondary70 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_300), + secondary60 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_400), + secondary50 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_500), + secondary40 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_600), + secondary30 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_700), + secondary20 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_800), + secondary10 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_900), + secondary0 = ColorResourceHelper.getColor(context, android.R.color.system_accent2_1000), + + // The tertiary tonal range from the generated dynamic color palette. + tertiary100 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_0), + tertiary99 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_10), + tertiary95 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_50), + tertiary90 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_100), + tertiary80 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_200), + tertiary70 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_300), + tertiary60 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_400), + tertiary50 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_500), + tertiary40 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_600), + tertiary30 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_700), + tertiary20 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_800), + tertiary10 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_900), + tertiary0 = ColorResourceHelper.getColor(context, android.R.color.system_accent3_1000), + ) + +private object ColorResourceHelper { + @DoNotInline + fun getColor(context: Context, @ColorRes id: Int): Color { + return Color(context.resources.getColor(id, context.theme)) + } +} diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml index dd251df3a..58d110f09 100644 --- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml +++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml @@ -8266,6 +8266,14 @@ android:protectionLevel="signature" android:featureFlag="com.android.hardware.input.manage_key_gestures" /> + <!-- Allows applications to register listeners for key activeness through + InputManagerService. + <p>Protection level: signature + @hide --> + <permission android:name="android.permission.LISTEN_FOR_KEY_ACTIVITY" + android:protectionLevel="signature" + android:featureFlag="com.android.hardware.input.key_event_activity_detection"/> + <uses-permission android:name="android.permission.HANDLE_QUERY_PACKAGE_RESTART" /> <!-- Allows financed device kiosk apps to perform actions on the Device Lock service diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt index bd22cb5bc..ccc5a0a5e 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt @@ -1129,9 +1129,16 @@ abstract class BaseUsePermissionTest : BasePermissionTest() { } } } + protected fun navigateToIndividualPermissionSetting( + permission: String, + manuallyNavigate: Boolean = false, + ) { + navigateToIndividualPermissionSetting(permission, APP_PACKAGE_NAME, manuallyNavigate) + } protected fun navigateToIndividualPermissionSetting( permission: String, + packageName: String, manuallyNavigate: Boolean = false, ) { val useLegacyNavigation = isWatch || isAutomotive || manuallyNavigate @@ -1150,7 +1157,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() { runWithShellPermissionIdentity { context.startActivity( Intent(Intent.ACTION_MANAGE_APP_PERMISSION).apply { - putExtra(Intent.EXTRA_PACKAGE_NAME, APP_PACKAGE_NAME) + putExtra(Intent.EXTRA_PACKAGE_NAME, packageName) putExtra(Intent.EXTRA_PERMISSION_NAME, permission) putExtra(Intent.EXTRA_USER, Process.myUserHandle()) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) diff --git a/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt index d41c7454f..5e2e40d20 100644 --- a/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt +++ b/tests/cts/permissionui/src/android/permissionui/cts/MediaPermissionTest.kt @@ -17,12 +17,18 @@ package android.permissionui.cts import android.Manifest +import android.app.role.RoleManager +import android.content.pm.PackageManager import android.os.Build +import android.platform.test.annotations.AsbSecurityTest import androidx.test.filters.FlakyTest import androidx.test.filters.SdkSuppress +import androidx.test.uiautomator.By import com.android.compatibility.common.util.CddTest import com.android.compatibility.common.util.SystemUtil +import org.junit.Assert import org.junit.Assume +import org.junit.Assume.assumeTrue import org.junit.Test /** @@ -180,4 +186,33 @@ class MediaPermissionTest : BaseUsePermissionTest() { assertAppHasPermission(Manifest.permission.READ_MEDIA_VIDEO, true) assertAppHasPermission(Manifest.permission.READ_MEDIA_IMAGES, true) } + + + @Test + @AsbSecurityTest(cveBugId = [315320090]) + fun testGalleryAppListedAsFixed() { + val galleryPkgs = SystemUtil.callWithShellPermissionIdentity { + context.getSystemService(RoleManager::class.java) + .getRoleHolders(SYSTEM_GALLERY_ROLE_NAME) + } + assumeTrue(galleryPkgs.isNotEmpty()) + val galleryPkg = galleryPkgs[0] + val checkPermissionResult = SystemUtil.callWithShellPermissionIdentity { + packageManager.checkPermission(Manifest.permission.READ_MEDIA_IMAGES, galleryPkg) + } + assumeTrue(checkPermissionResult == PackageManager.PERMISSION_GRANTED) + navigateToIndividualPermissionSetting(Manifest.permission.READ_MEDIA_IMAGES, galleryPkg) + // Attempt to deny the permission. It should not show the + // "denying default permission dialog" + click(By.res(DENY_RADIO_BUTTON)) + try { + waitFindObject(By.res(CANCEL_BUTTON_ID), 1000L) + Assert.fail("expected not to find the default deny dialog") + } catch (_: Exception) {} + } + + companion object { + private val SYSTEM_GALLERY_ROLE_NAME = "android.app.role.SYSTEM_GALLERY" + private val CANCEL_BUTTON_ID = "android:id/button1" + } } |