summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/AndroidManifest.xml1
-rw-r--r--PermissionController/res/drawable/ic_android_security_privacy.xml11
-rw-r--r--PermissionController/res/drawable/ic_error.xml10
-rw-r--r--PermissionController/res/drawable/ic_security_update_good.xml11
-rw-r--r--PermissionController/res/layout/car_switch_button_preference.xml68
-rw-r--r--PermissionController/res/layout/radio_button_preference_widget.xml2
-rw-r--r--PermissionController/res/layout/switch_button_preference_widget.xml30
-rw-r--r--PermissionController/res/values-ar/strings.xml2
-rw-r--r--PermissionController/res/values-az/strings.xml12
-rw-r--r--PermissionController/res/values-bn/strings.xml12
-rw-r--r--PermissionController/res/values-bs/strings.xml6
-rw-r--r--PermissionController/res/values-eu/strings.xml2
-rw-r--r--PermissionController/res/values-fr/strings.xml2
-rw-r--r--PermissionController/res/values-gl/strings.xml12
-rw-r--r--PermissionController/res/values-is/strings.xml12
-rw-r--r--PermissionController/res/values-iw/strings.xml4
-rw-r--r--PermissionController/res/values-lv/strings.xml12
-rw-r--r--PermissionController/res/values-mk/strings.xml12
-rw-r--r--PermissionController/res/values-ml/strings.xml12
-rw-r--r--PermissionController/res/values-mn/strings.xml12
-rw-r--r--PermissionController/res/values-ne/strings.xml12
-rw-r--r--PermissionController/res/values-night/themes.xml2
-rw-r--r--PermissionController/res/values-or/strings.xml12
-rw-r--r--PermissionController/res/values-pa/strings.xml12
-rw-r--r--PermissionController/res/values-pl/strings.xml12
-rw-r--r--PermissionController/res/values-ru/strings.xml12
-rw-r--r--PermissionController/res/values-si/strings.xml12
-rw-r--r--PermissionController/res/values-sq/strings.xml12
-rw-r--r--PermissionController/res/values-sv/strings.xml2
-rw-r--r--PermissionController/res/values-zh-rCN/strings.xml12
-rw-r--r--PermissionController/res/values/dimens.xml2
-rw-r--r--PermissionController/res/values/overlayable.xml6
-rw-r--r--PermissionController/res/values/strings.xml9
-rw-r--r--PermissionController/res/values/themes.xml6
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/compat/AppOpsManagerCompat.java8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java1
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java71
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/television/TEST_MAPPING19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt10
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt73
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt146
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt22
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt124
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/RemoteConnectionProgressIndicator.kt75
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ResponsiveDialog.kt15
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/RemoteActivityHelper.kt86
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearEnhancedConfirmationViewModel.kt77
-rw-r--r--PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt28
-rw-r--r--flags/flags.aconfig18
-rw-r--r--service/java/com/android/ecm/EnhancedConfirmationService.java1
-rw-r--r--service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java1
-rw-r--r--service/java/com/android/role/persistence/RolesPersistenceImpl.java1
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml3
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt52
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt10
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt55
61 files changed, 1101 insertions, 262 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index c0d6c2907..ad34330cb 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -65,7 +65,6 @@
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
<uses-permission android:name="android.permission.GET_APP_METADATA" />
- <uses-permission android:name="android.permission.NFC_PREFERRED_PAYMENT_INFO" />
<uses-permission android:name="android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES" />
<uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
<uses-permission android:name="android.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION" />
diff --git a/PermissionController/res/drawable/ic_android_security_privacy.xml b/PermissionController/res/drawable/ic_android_security_privacy.xml
new file mode 100644
index 000000000..e2cad5a99
--- /dev/null
+++ b/PermissionController/res/drawable/ic_android_security_privacy.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,797Q522,774 554.5,738Q587,702 587,651Q587,587 535,547Q483,507 428,472Q379,440 350,390Q321,340 321,282Q321,265 323,248.5Q325,232 330,215L240,247Q240,247 240,247Q240,247 240,247L240,412Q240,546 299.5,639Q359,732 480,797ZM666,629Q693,583 706.5,529Q720,475 720,412L720,247Q720,247 720,247Q720,247 720,247L480,161Q442,175 421.5,208.5Q401,242 401,282Q401,325 426.5,359.5Q452,394 489,416Q552,454 605.5,504Q659,554 666,629Q666,629 666,629Q666,629 666,629ZM480,880Q473,880 466.5,878.5Q460,877 454,874Q306,798 233,685.5Q160,573 160,412L160,248Q160,222 174.5,201Q189,180 213,172L453,86Q460,84 466.5,82Q473,80 480,80Q489,80 507,86L747,172Q771,180 785.5,200.5Q800,221 800,247L800,412Q800,573 725.5,686Q651,799 505,874Q499,877 493,878.5Q487,880 480,880Z"/>
+</vector>
diff --git a/PermissionController/res/drawable/ic_error.xml b/PermissionController/res/drawable/ic_error.xml
new file mode 100644
index 000000000..8355c11ca
--- /dev/null
+++ b/PermissionController/res/drawable/ic_error.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M480,680Q497,680 508.5,668.5Q520,657 520,640Q520,623 508.5,611.5Q497,600 480,600Q463,600 451.5,611.5Q440,623 440,640Q440,657 451.5,668.5Q463,680 480,680ZM440,520L520,520L520,280L440,280L440,520ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
+</vector>
diff --git a/PermissionController/res/drawable/ic_security_update_good.xml b/PermissionController/res/drawable/ic_security_update_good.xml
new file mode 100644
index 000000000..59e7a67fa
--- /dev/null
+++ b/PermissionController/res/drawable/ic_security_update_good.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M442,600L330,488L386,432L442,488L584,346L640,402L442,600ZM280,920Q247,920 223.5,896.5Q200,873 200,840L200,120Q200,87 223.5,63.5Q247,40 280,40L680,40Q713,40 736.5,63.5Q760,87 760,120L760,840Q760,873 736.5,896.5Q713,920 680,920L280,920ZM280,800L280,840Q280,840 280,840Q280,840 280,840L680,840Q680,840 680,840Q680,840 680,840L680,800L280,800ZM280,720L680,720L680,240L280,240L280,720ZM280,160L680,160L680,120Q680,120 680,120Q680,120 680,120L280,120Q280,120 280,120Q280,120 280,120L280,160ZM280,160L280,120Q280,120 280,120Q280,120 280,120L280,120Q280,120 280,120Q280,120 280,120L280,160L280,160ZM280,800L280,800L280,840Q280,840 280,840Q280,840 280,840L280,840Q280,840 280,840Q280,840 280,840L280,800Z"/>
+</vector>
diff --git a/PermissionController/res/layout/car_switch_button_preference.xml b/PermissionController/res/layout/car_switch_button_preference.xml
new file mode 100644
index 000000000..a2c2dcd8f
--- /dev/null
+++ b/PermissionController/res/layout/car_switch_button_preference.xml
@@ -0,0 +1,68 @@
+<?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
+ -->
+
+<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="wrap_content"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
+
+ <FrameLayout
+ android:id="@android:id/widget_frame"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:minWidth="?android:attr/listPreferredItemHeightSmall"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <TextView
+ android:id="@android:id/title"
+ style="@style/AppPermissionLocationAccuracyTitle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:paddingBottom="@dimen/car_preference_row_vertical_margin"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingTop="@dimen/car_preference_row_vertical_margin"
+ android:singleLine="true"
+ android:text="@string/app_permission_location_accuracy"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ app:layout_constraintEnd_toStartOf="@android:id/widget_frame"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintWidth_default="spread" />
+
+ <TextView
+ android:id="@android:id/summary"
+ style="@style/AppPermissionLocationAccuracySubtitle"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/car_preference_row_vertical_margin"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:text="@string/app_permission_location_accuracy_subtitle"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ app:layout_constraintEnd_toStartOf="@android:id/widget_frame"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@android:id/title"
+ app:layout_constraintWidth_default="spread" />
+
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/PermissionController/res/layout/radio_button_preference_widget.xml b/PermissionController/res/layout/radio_button_preference_widget.xml
index cd2a2ce42..9bff4e46e 100644
--- a/PermissionController/res/layout/radio_button_preference_widget.xml
+++ b/PermissionController/res/layout/radio_button_preference_widget.xml
@@ -19,7 +19,7 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:minWidth="56dp"
+ android:minWidth="@dimen/toggle_preference_container_min_width"
android:layout_height="match_parent">
<RadioButton
diff --git a/PermissionController/res/layout/switch_button_preference_widget.xml b/PermissionController/res/layout/switch_button_preference_widget.xml
new file mode 100644
index 000000000..f5a2d595b
--- /dev/null
+++ b/PermissionController/res/layout/switch_button_preference_widget.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:minWidth="@dimen/toggle_preference_container_min_width"
+ android:layout_height="match_parent">
+
+ <Switch
+ android:id="@+id/location_accuracy_switch"
+ android:checked="false"
+ android:duplicateParentState="true"
+ style="@style/AppPermissionLocationAccuracySwitch" />
+</FrameLayout>
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index 76159b78c..10ecc0d12 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -674,7 +674,7 @@
<string name="enhanced_confirmation_dialog_desc" msgid="5921240234843839219">"للحفاظ على أمانك، هذا الإعداد غير متوفِّر حاليًا."</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">&lt;br&gt;&lt;br&gt;</xliff:g>من المحتمل ألا يعمل التطبيق بشكل صحيح إذا لم يحصل على هذا الإذن المقيَّد. &lt;a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>&gt;مزيد من المعلومات حول كيفية منح الأذونات&lt;/a&gt;"</string>
- <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"لم يتم السماح للتطبيق بأن يُستخدَم كـ <xliff:g id="ROLE_NAME">%1$s</xliff:g> تلقائيًا"</string>
+ <string name="enhanced_confirmation_dialog_title_role" msgid="1737023798483772780">"لم يُسمَح للتطبيق بأن يكون <xliff:g id="ROLE_NAME">%1$s</xliff:g> التلقائي"</string>
<string name="enhanced_confirmation_dialog_desc_role" msgid="6369601947905234551">"‏طلب التطبيق أذونات الوصول إلى المعلومات الحساسة، ما قد يعرّض معلوماتك الشخصية والمالية للخطر.<xliff:g id="ID_1">&lt;br&gt;&lt;br&gt;</xliff:g>من المحتمل ألا يعمل التطبيق بشكل صحيح إذا لم يحصل على هذه الأذونات المقيَّدة. &lt;a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>&gt;مزيد من المعلومات حول كيفية منح الأذونات&lt;/a&gt;"</string>
<string name="enhanced_confirmation_dialog_title_settings_default" msgid="1858092969721041576">"تم منع التطبيق من الوصول"</string>
<string name="enhanced_confirmation_dialog_desc_settings_default" msgid="6911632348359332981">"‏إذا منحت التطبيق هذا الإذن، يمكن أن تتعرّض معلوماتك الشخصية والمالية للخطر.<xliff:g id="ID_1">&lt;br&gt;&lt;br&gt;</xliff:g>من المحتمل ألا يعمل التطبيق بشكل صحيح إذا لم يحصل على هذا الإذن المقيَّد. &lt;a href=<xliff:g id="LEARN_MORE_LINK">%1$s</xliff:g>&gt;مزيد من المعلومات حول كيفية منح الأذونات&lt;/a&gt;"</string>
diff --git a/PermissionController/res/values-az/strings.xml b/PermissionController/res/values-az/strings.xml
index d994d4c95..5e7418bb7 100644
--- a/PermissionController/res/values-az/strings.xml
+++ b/PermissionController/res/values-az/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"icazələr"</string>
<string name="cancel" msgid="8943320028373963831">"Ləğv edin"</string>
<string name="back" msgid="6249950659061523680">"Geri"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Bağlayın"</string>
<string name="available" msgid="6007778121920339498">"Əlçatan"</string>
<string name="blocked" msgid="9195547604866033708">"Bloklanıb"</string>
<string name="on" msgid="280241003226755921">"Aktiv"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"OK"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"İcazə sorğusu dayandırıldı"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Bu tətbiqə əlavə icazələr lazımdır, lakin yayım sessiyasında icazə vermək olmur. Əvvəlcə telefonda icazə verin."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Təcili zəng və ya mətn mesajı üçün"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Məkan təcili xidmətlərə göndərildi"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Bu tətbiq təcili nömrəyə zəng edərkən və ya mesaj göndərərkən cihazınızın məkanına daxil oldu. Bu hal hətta tətbiqin məkan icazəsi olmadıqda və ya cihaz məkanı sönülü olduqda da baş verə bilər. "<a href="https://support.google.com/android/answer/9319337">"Ətraflı məlumat"</a></string>
</resources>
diff --git a/PermissionController/res/values-bn/strings.xml b/PermissionController/res/values-bn/strings.xml
index b18f03773..a1d9b5ae1 100644
--- a/PermissionController/res/values-bn/strings.xml
+++ b/PermissionController/res/values-bn/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"অনুমতি"</string>
<string name="cancel" msgid="8943320028373963831">"বাতিল করুন"</string>
<string name="back" msgid="6249950659061523680">"ফিরুন"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"বন্ধ করুন"</string>
<string name="available" msgid="6007778121920339498">"উপলভ্য"</string>
<string name="blocked" msgid="9195547604866033708">"ব্লক করা হয়েছে"</string>
<string name="on" msgid="280241003226755921">"চালু করা আছে"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ঠিক আছে"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"অনুমতির অনুরোধ ব্লক করা হয়েছে"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"এই অ্যাপ অতিরিক্ত অনুমতির জন্য অনুরোধ করছে, কিন্তু স্ট্রিমিং সেশন চলাকালীন অনুমতি দেওয়া যাবে না। প্রথমে আপনার ফোনে অনুমতি দিন।"</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"জরুরি কল বা মেসেজের জন্য"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"জরুরি পরিষেবায় লোকেশন পাঠানো হয়েছে"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"আপনি যখন একটি জরুরি নম্বরে কল বা মেসেজ পাঠানোর সময়, অ্যাপটি আপনার ডিভাইসের লোকেশন অ্যাক্সেস করেছে। অ্যাপের ডিভাইসের লোকেশন অ্যাক্সেস করার অনুমতি না থাকলে অথবা লোকেশন বন্ধ থাকলেও এটি হতে পারে। "<a href="https://support.google.com/android/answer/9319337">"আরও জানুন"</a></string>
</resources>
diff --git a/PermissionController/res/values-bs/strings.xml b/PermissionController/res/values-bs/strings.xml
index 0b9a62365..e9f6f00e0 100644
--- a/PermissionController/res/values-bs/strings.xml
+++ b/PermissionController/res/values-bs/strings.xml
@@ -682,7 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Uredu"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Zahtjev za odobrenje je potisnut"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Aplikacija traži dodatna odobrenja, ali se ona ne mogu dati u sesiji prijenosa. Najprije dajte odobrenje na telefonu."</string>
- <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Za pozive ili poruke hitnim službama"</string>
- <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Lokacija poslana hitnim službama"</string>
- <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Ova je aplikacija pristupila lokaciji vašeg uređaja prilikom upućivanja poziva ili poruke na broj hitne službe. To se može dogoditi čak i kad aplikacija nema dopuštenje za lokaciju ili je lokacija uređaja isključena. "<a href="https://support.google.com/android/answer/9319337">"Saznajte više"</a></string>
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Za hitni poziv ili poruku"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Lokacija je poslana hitnim službama"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Ova aplikacija je pristupila lokaciji uređaja tokom poziva ili slanja poruke broju za hitne slučajeve. To se može dogoditi čak i kada aplikacija nema odobrenje za lokaciju ili je lokacija uređaja isključena. "<a href="https://support.google.com/android/answer/9319337">"Saznajte više"</a></string>
</resources>
diff --git a/PermissionController/res/values-eu/strings.xml b/PermissionController/res/values-eu/strings.xml
index 025467c8a..60857ef47 100644
--- a/PermissionController/res/values-eu/strings.xml
+++ b/PermissionController/res/values-eu/strings.xml
@@ -622,7 +622,7 @@
<string name="safety_center_background_location_access_reminder_title" msgid="5477847038103863843">"Berrikusi kokapena atzeko planoan erabiltzeko baimena duen aplikazioa"</string>
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Aplikazioak beti erabil dezake kokapena, nahiz eta itxita egon.\n\nSegurtasun- eta larrialdi-aplikazio batzuek atzeko planoan kokapena erabiltzeko baimena behar dute behar bezala funtzionatzeko."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Aldatu da sarbidea"</string>
- <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Ikusi kokapenaren azken erabilera"</string>
+ <string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Ikusi kokapenaren azkenaldiko erabilera"</string>
<string name="privacy_controls_title" msgid="7605929972256835199">"Pribatutasun-ezarpenak"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Kamera erabiltzeko baimena"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Mikrofonoa erabiltzeko baimena"</string>
diff --git a/PermissionController/res/values-fr/strings.xml b/PermissionController/res/values-fr/strings.xml
index 4afe32dbc..b4f71fcf2 100644
--- a/PermissionController/res/values-fr/strings.xml
+++ b/PermissionController/res/values-fr/strings.xml
@@ -684,5 +684,5 @@
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Cette appli demande des autorisations supplémentaires, mais il est impossible d\'accorder des autorisations lors d\'une session de streaming. Accordez tout d\'abord l\'autorisation sur votre téléphone."</string>
<string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Pour les messages ou les appels d\'urgence"</string>
<string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Position envoyée aux services d\'urgence"</string>
- <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Cette application a accédé à la position de votre appareil pendant un appel ou l\'envoi d\'un message vers un numéro d\'urgence. Cette action se produit même lorsque l\'application ne dispose pas de l\'autorisation d\'accéder à la position ou lorsque la position de l\'appareil est désactivée. "<a href="https://support.google.com/android/answer/9319337">"En savoir plus"</a></string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Cette application a accédé à la position de votre appareil lors d\'un appel ou de l\'envoi d\'un message vers un numéro d\'urgence. Cela peut se produire même si l\'application ne dispose pas de l\'autorisation d\'accéder à la position ou lorsque la position de l\'appareil est désactivée. "<a href="https://support.google.com/android/answer/9319337">"En savoir plus"</a></string>
</resources>
diff --git a/PermissionController/res/values-gl/strings.xml b/PermissionController/res/values-gl/strings.xml
index 645a96229..d1e9f3f43 100644
--- a/PermissionController/res/values-gl/strings.xml
+++ b/PermissionController/res/values-gl/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"permisos"</string>
<string name="cancel" msgid="8943320028373963831">"Cancelar"</string>
<string name="back" msgid="6249950659061523680">"Atrás"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Pechar"</string>
<string name="available" msgid="6007778121920339498">"Dispoñible"</string>
<string name="blocked" msgid="9195547604866033708">"Bloqueado"</string>
<string name="on" msgid="280241003226755921">"Activado"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Aceptar"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Eliminouse a solicitude de permiso"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Esta aplicación solicita permisos adicionais, pero non se poden conceder nunha sesión de reprodución en tempo real. Primeiro tes que dar o permiso no teu teléfono."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Para mensaxes de texto ou chamadas de emerxencia"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Enviouse a localización aos servizos de emerxencia"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Esta aplicación accedeu á localización do teu dispositivo mentres facías unha chamada ou enviabas unha mensaxe de texto a un número de emerxencia. Isto pode ocorrer mesmo se a aplicación non ten permiso de acceso á localización ou a localización do dispositivo está desactivada. "<a href="https://support.google.com/android/answer/9319337">"Máis información"</a></string>
</resources>
diff --git a/PermissionController/res/values-is/strings.xml b/PermissionController/res/values-is/strings.xml
index 4fb572f4e..3ef031549 100644
--- a/PermissionController/res/values-is/strings.xml
+++ b/PermissionController/res/values-is/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"heimildir"</string>
<string name="cancel" msgid="8943320028373963831">"Hætta við"</string>
<string name="back" msgid="6249950659061523680">"Til baka"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Loka"</string>
<string name="available" msgid="6007778121920339498">"Tiltækt"</string>
<string name="blocked" msgid="9195547604866033708">"Lokað á"</string>
<string name="on" msgid="280241003226755921">"Kveikt"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Í lagi"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Heimildarbeiðni hafnað"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Þetta forrit biður um viðbótarheimildir en ekki er hægt að veita heimildir í streymislotu. Veittu heimildina í símanum fyrst."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Fyrir neyðarsímtal eða -skilaboð"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Staðsetning send til neyðarþjónustu"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Þetta forrit fékk aðgang að staðsetningu tækisins vegna símtals eða skilaboða í neyðarnúmer. Þetta getur gerst jafnvel þótt forritið sé ekki með staðsetningarheimild eða slökkt sé á staðsetningu tækisins. "<a href="https://support.google.com/android/answer/9319337">"Nánar"</a></string>
</resources>
diff --git a/PermissionController/res/values-iw/strings.xml b/PermissionController/res/values-iw/strings.xml
index bb35a88a3..452df0486 100644
--- a/PermissionController/res/values-iw/strings.xml
+++ b/PermissionController/res/values-iw/strings.xml
@@ -56,7 +56,7 @@
<string name="grant_dialog_button_change_to_precise_location" msgid="3273115879467236033">"לשנות למיקום מדויק"</string>
<string name="grant_dialog_button_keey_approximate_location" msgid="438025182769080011">"להמשיך עם מיקום משוער"</string>
<string name="grant_dialog_button_allow_one_time" msgid="2618088516449706391">"רק הפעם"</string>
- <string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"להתיר כל הזמן"</string>
+ <string name="grant_dialog_button_allow_background" msgid="8236044729434367833">"כן, כל הזמן"</string>
<string name="grant_dialog_button_allow_all_files" msgid="4955436994954829894">"אישור לניהול כל הקבצים"</string>
<string name="grant_dialog_button_allow_media_only" msgid="4832877658422573832">"אישור גישה לקבצי מדיה"</string>
<string name="app_permissions_breadcrumb" msgid="5136969550489411650">"אפליקציות"</string>
@@ -110,7 +110,7 @@
<!-- no translation found for background_access_chooser_dialog_choices:0 (1351721623256561996) -->
<!-- no translation found for background_access_chooser_dialog_choices:1 (9127301153688725448) -->
<!-- no translation found for background_access_chooser_dialog_choices:2 (4305536986042401191) -->
- <string name="permission_access_always" msgid="1474641821883823446">"להתיר כל הזמן"</string>
+ <string name="permission_access_always" msgid="1474641821883823446">"כן, כל הזמן"</string>
<string name="permission_access_only_foreground" msgid="7801170728159326195">"רק כשהאפליקציה בשימוש"</string>
<string name="permission_access_never" msgid="4647014230217936900">"אין אישור"</string>
<string name="loading" msgid="4789365003890741082">"בטעינה…"</string>
diff --git a/PermissionController/res/values-lv/strings.xml b/PermissionController/res/values-lv/strings.xml
index 35b3ea108..a8f9e3ac1 100644
--- a/PermissionController/res/values-lv/strings.xml
+++ b/PermissionController/res/values-lv/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"atļaujas"</string>
<string name="cancel" msgid="8943320028373963831">"Atcelt"</string>
<string name="back" msgid="6249950659061523680">"Atpakaļ"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Aizvērt"</string>
<string name="available" msgid="6007778121920339498">"Pieejama"</string>
<string name="blocked" msgid="9195547604866033708">"Bloķēta"</string>
<string name="on" msgid="280241003226755921">"Ieslēgta"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Labi"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Atļaujas pieprasījums bloķēts"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Šī lietotne pieprasa papildu atļaujas, taču atļaujas nevar piešķirt straumēšanas sesijā. Vispirms piešķiriet attiecīgo atļauju savā tālrunī."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Ārkārtas izsaukumam (zvanam vai īsziņai)"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Ārkārtas palīdzības dienestiem tika nosūtīti atrašanās vietas dati"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Šī lietotne piekļuva ierīces atrašanās vietas datiem, zvanot vai sūtot īsziņu uz ārkārtas numuru. Tas var notikt pat tad, ja lietotnei nav atrašanās vietas atļaujas vai ierīcē ir izslēgta atrašanās vietas noteikšana. "<a href="https://support.google.com/android/answer/9319337">"Uzziniet vairāk."</a></string>
</resources>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index 3c51b26f9..193d2a027 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"дозволи"</string>
<string name="cancel" msgid="8943320028373963831">"Откажи"</string>
<string name="back" msgid="6249950659061523680">"Назад"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Затвори"</string>
<string name="available" msgid="6007778121920339498">"Дозволен"</string>
<string name="blocked" msgid="9195547604866033708">"Блокиран"</string>
<string name="on" msgid="280241003226755921">"Вклучено"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Во ред"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Барањето за дозвола е потиснато"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Апликацијава бара дополнителни дозволи, но нив не може да ги доделите во сесија за стриминг. Прво доделете ја дозволата на вашиот телефон."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"За итен повик или порака"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Локацијата е испратена до службите за итни случаи"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Оваа апликација пристапи до локацијата на вашиот уред при размена на повик или пораки со број за итни случаи. Ова може да се случи дури и кога апликацијата нема дозвола за локација или кога локацијата на уредот е исклучена. "<a href="https://support.google.com/android/answer/9319337">"Дознајте повеќе"</a></string>
</resources>
diff --git a/PermissionController/res/values-ml/strings.xml b/PermissionController/res/values-ml/strings.xml
index 04d9a8ae4..fac49c11f 100644
--- a/PermissionController/res/values-ml/strings.xml
+++ b/PermissionController/res/values-ml/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"അനുമതികൾ"</string>
<string name="cancel" msgid="8943320028373963831">"റദ്ദാക്കുക"</string>
<string name="back" msgid="6249950659061523680">"മടങ്ങുക"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"അടയ്ക്കുക"</string>
<string name="available" msgid="6007778121920339498">"ലഭ്യമാണ്"</string>
<string name="blocked" msgid="9195547604866033708">"ബ്ലോക്ക് ചെയ്‌തിരിക്കുന്നു"</string>
<string name="on" msgid="280241003226755921">"ഓണാണ്"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ശരി"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"അനുമതി അഭ്യർത്ഥന കാഴ്ച്ചയിൽ നിന്ന് മറച്ചു"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"ഈ ആപ്പ് അധിക അനുമതികൾ അഭ്യർത്ഥിക്കുന്നു, എന്നാൽ സ്‌ട്രീമിംഗ് സെഷനിടയിൽ അനുമതികൾ നൽകാനാകില്ല. ആദ്യം നിങ്ങളുടെ ഫോണിൽ അനുമതി നൽകുക."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"എമർജൻസി കോളിനോ ടെക്സ്റ്റിനോ ആയി"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"അടിയന്തര സേവനങ്ങളിലേക്ക് ലൊക്കേഷൻ അയച്ചു"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"അടിയന്തര നമ്പറിലേക്ക് ഒരു കോൾ ചെയ്യുമ്പോഴോ ടെക്സ്റ്റ് ചെയ്യുമ്പോഴോ ഈ ആപ്പ് നിങ്ങളുടെ ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്തു. ആപ്പിന് ലൊക്കേഷൻ അനുമതി ഇല്ലാത്തപ്പോഴോ ഉപകരണ ലൊക്കേഷൻ ഓഫായിരിക്കുമ്പോഴോ പോലും ഇത് സംഭവിക്കാം. "<a href="https://support.google.com/android/answer/9319337">"കൂടുതലറിയുക"</a></string>
</resources>
diff --git a/PermissionController/res/values-mn/strings.xml b/PermissionController/res/values-mn/strings.xml
index a55e61d1f..af990c0d2 100644
--- a/PermissionController/res/values-mn/strings.xml
+++ b/PermissionController/res/values-mn/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"зөвшөөрөл"</string>
<string name="cancel" msgid="8943320028373963831">"Болих"</string>
<string name="back" msgid="6249950659061523680">"Буцах"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Хаах"</string>
<string name="available" msgid="6007778121920339498">"Боломжтой"</string>
<string name="blocked" msgid="9195547604866033708">"Блоклосон"</string>
<string name="on" msgid="280241003226755921">"Асаалттай"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ОК"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Зөвшөөрлийн хүсэлтийг зогсоосон"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Энэ апп нэмэлт зөвшөөрөл хүсэж байгаа ч дамжуулалтын харилцан үйлдлийн үеэр зөвшөөрөл олгох боломжгүй. Эхлээд утсан дээрээ зөвшөөрөл олгоно уу."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Яаралтай дуудлага хийх эсвэл мессеж илгээх зорилгоор"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Байршлыг яаралтай тусламжийн үйлчилгээнүүд рүү илгээсэн"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Энэ апп яаралтай тусламжийн утасны дугаар луу хийсэн дуудлага эсвэл илгээсэн мессежийн үеэр таны төхөөрөмжийн байршилд хандсан. Энэ нь аппад байршлын зөвшөөрөл байхгүй эсвэл төхөөрөмжийн байршил унтраалттай байсан ч тохиолдож болно. "<a href="https://support.google.com/android/answer/9319337">"Нэмэлт мэдээлэл авах"</a></string>
</resources>
diff --git a/PermissionController/res/values-ne/strings.xml b/PermissionController/res/values-ne/strings.xml
index 066683ebb..6632a6ef8 100644
--- a/PermissionController/res/values-ne/strings.xml
+++ b/PermissionController/res/values-ne/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"अनुमतिहरू"</string>
<string name="cancel" msgid="8943320028373963831">"रद्द गर्नुहोस्"</string>
<string name="back" msgid="6249950659061523680">"पछाडि जानुहोस्"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"बन्द गर्नुहोस्"</string>
<string name="available" msgid="6007778121920339498">"उपलब्ध"</string>
<string name="blocked" msgid="9195547604866033708">"ब्लक गरिएको"</string>
<string name="on" msgid="280241003226755921">"अन छ"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ठिक छ"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"अनुमतिसम्बन्धी अनुरोध रद्द गरिएको छ"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"यो एपले अतिरिक्त अनुमति मागिरहेको छ तर स्ट्रिमिङ सत्रमा अनुमति दिन मिल्दैन। सर्वप्रथम आफ्नो फोनमा अनुमति दिनुहोस्।"</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"आपत्कालीन अवस्थामा यो नम्बरमा कल गर्नुहोस् वा टेक्स्ट म्यासेज पठाउनुहोस्"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"आपत्कालीन सेवाहरूमा लोकेसन पठाइएको छ"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"यो एपले आपत्कालीन नम्बरमा कल वा टेक्स्ट म्यासेज गर्ने बेलामा तपाईंको डिभाइसको लोकेसन एक्सेस गरेको छ। यो एपलाई लोकेसन प्रयोग गर्ने अनुमति नदिइएका वा यो डिभाइसको लोकेसन अफ गरिएका अवस्थामा पनि यस्तो हुन सक्छ। "<a href="https://support.google.com/android/answer/9319337">"थप जान्नुहोस्"</a></string>
</resources>
diff --git a/PermissionController/res/values-night/themes.xml b/PermissionController/res/values-night/themes.xml
index 7ac9b190b..8c6a10db5 100644
--- a/PermissionController/res/values-night/themes.xml
+++ b/PermissionController/res/values-night/themes.xml
@@ -41,4 +41,6 @@
</style>
<style name="Theme.DeviceDefault.Dialog.NoActionBar.DayNight" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar" />
+
+ <style name="Theme.DeviceDefault.Dialog.Alert.DayNight" parent="@android:style/Theme.DeviceDefault.Dialog.Alert" />
</resources>
diff --git a/PermissionController/res/values-or/strings.xml b/PermissionController/res/values-or/strings.xml
index ff0e68809..8b1655efc 100644
--- a/PermissionController/res/values-or/strings.xml
+++ b/PermissionController/res/values-or/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"ଅନୁମତିଗୁଡ଼ିକ"</string>
<string name="cancel" msgid="8943320028373963831">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="back" msgid="6249950659061523680">"ପଛକୁ ଫେରନ୍ତୁ"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"ବନ୍ଦ କରନ୍ତୁ"</string>
<string name="available" msgid="6007778121920339498">"ଉପଲବ୍ଧ ଅଛି"</string>
<string name="blocked" msgid="9195547604866033708">"ବ୍ଲକ କରାଯାଇଛି"</string>
<string name="on" msgid="280241003226755921">"ଚାଲୁ ଅଛି"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ଠିକ ଅଛି"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"ଅନୁମତି ଅନୁରୋଧକୁ ବନ୍ଦ କରାଯାଇଛି"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"ଏହି ଆପ ଅତିରିକ୍ତ ଅନୁମତି ପାଇଁ ଅନୁରୋଧ କରୁଛି, ଏକ ଷ୍ଟ୍ରିମିଂ ସେସନରେ ଅନୁମତି ଦିଆଯାଇପାରିବ ନାହିଁ। ପ୍ରଥମେ ଆପଣଙ୍କ ଫୋନରେ ଅନୁମତି ଦିଅନ୍ତୁ।"</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"ଜରୁରୀକାଳୀନ କଲ କିମ୍ବା ଟେକ୍ସଟ ପାଇଁ"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"ଜରୁରୀକାଳୀନ ସେବାଗୁଡ଼ିକୁ ଲୋକେସନ ପଠାଯାଇଛି"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"ଏକ ଜରୁରୀକାଳୀନ ନମ୍ବରକୁ କଲ କରାଯିବା କିମ୍ବା ଟେକ୍ସଟ ପଠାଇବା ସମୟରେ ଏହି ଆପ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନକୁ ଆକ୍ସେସ କରିଛି। ଆପ ପାଖରେ ଲୋକେସନ ଅନୁମତି ନଥିଲେ କିମ୍ବା ଡିଭାଇସର ଲୋକେସନ ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଏହା ହୋଇପାରେ। "<a href="https://support.google.com/android/answer/9319337">"ଅଧିକ ଜାଣନ୍ତୁ"</a></string>
</resources>
diff --git a/PermissionController/res/values-pa/strings.xml b/PermissionController/res/values-pa/strings.xml
index c860460e3..0bbaf644a 100644
--- a/PermissionController/res/values-pa/strings.xml
+++ b/PermissionController/res/values-pa/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"ਇਜਾਜ਼ਤਾਂ"</string>
<string name="cancel" msgid="8943320028373963831">"ਰੱਦ ਕਰੋ"</string>
<string name="back" msgid="6249950659061523680">"ਪਿੱਛੇ"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"ਬੰਦ ਕਰੋ"</string>
<string name="available" msgid="6007778121920339498">"ਉਪਲਬਧ ਹੈ"</string>
<string name="blocked" msgid="9195547604866033708">"ਬਲਾਕ ਹੈ"</string>
<string name="on" msgid="280241003226755921">"ਚਾਲੂ ਹੈ"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ਠੀਕ ਹੈ"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"ਇਜਾਜ਼ਤ ਸੰਬੰਧੀ ਬੇਨਤੀ ਨੂੰ ਰੋਕਿਆ ਗਿਆ"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"ਇਹ ਐਪ ਵਧੀਕ ਇਜਾਜ਼ਤਾਂ ਦੀ ਬੇਨਤੀ ਕਰ ਰਹੀ ਹੈ, ਪਰ ਸਟ੍ਰੀਮਿੰਗ ਸੈਸ਼ਨ ਵਿੱਚ ਇਜਾਜ਼ਤਾਂ ਨਹੀਂ ਦਿੱਤੀਆਂ ਜਾ ਸਕਦੀਆਂ। ਪਹਿਲਾਂ ਆਪਣੇ ਫ਼ੋਨ \'ਤੇ ਇਜਾਜ਼ਤ ਦਿਓ।"</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"ਐਮਰਜੈਂਸੀ ਕਾਲ ਜਾਂ ਲਿਖਤ ਸੁਨੇਹੇ ਲਈ"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਨੂੰ ਭੇਜੀ ਗਈ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"ਇਸ ਐਪ ਵੱਲੋਂ ਐਮਰਜੈਂਸੀ ਨੰਬਰ \'ਤੇ ਕਾਲ ਕਰਨ ਜਾਂ ਲਿਖਤ ਸੁਨੇਹਾ ਭੇਜਣ ਦੌਰਾਨ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ ਗਈ। ਇਹ ਉਦੋਂ ਵੀ ਹੋ ਸਕਦਾ ਹੈ, ਜਦੋਂ ਐਪ ਕੋਲ ਟਿਕਾਣੇ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੁੰਦੀ ਹੈ ਜਾਂ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਸੁਵਿਧਾ ਬੰਦ ਹੁੰਦੀ ਹੈ। "<a href="https://support.google.com/android/answer/9319337">"ਹੋਰ ਜਾਣੋ"</a></string>
</resources>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index 504f9a0a0..0453d8ef8 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"uprawnienia"</string>
<string name="cancel" msgid="8943320028373963831">"Anuluj"</string>
<string name="back" msgid="6249950659061523680">"Wstecz"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Zamknij"</string>
<string name="available" msgid="6007778121920339498">"Odblokowany"</string>
<string name="blocked" msgid="9195547604866033708">"Zablokowany"</string>
<string name="on" msgid="280241003226755921">"Włączona"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"OK"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Prośba o uprawnienia została zablokowana"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Ta aplikacja prosi o dodatkowe uprawnienia, ale nie można ich przyznać w trakcie sesji strumieniowania. Najpierw przyznaj te uprawnienia na telefonie."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Na potrzeby połączenia lub SMS-a alarmowego"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Lokalizacja została wysłana do służb ratunkowych"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Ta aplikacja uzyskała dostęp do lokalizacji Twojego urządzenia podczas połączenia z numerem alarmowym lub wysyłania SMS-a pod ten numer. Może się tak zdarzyć, nawet jeśli aplikacja nie ma uprawnień do lokalizacji lub gdy lokalizacja jest wyłączona na urządzeniu. "<a href="https://support.google.com/android/answer/9319337">"Więcej informacji"</a></string>
</resources>
diff --git a/PermissionController/res/values-ru/strings.xml b/PermissionController/res/values-ru/strings.xml
index 4fa0397dc..61704a59e 100644
--- a/PermissionController/res/values-ru/strings.xml
+++ b/PermissionController/res/values-ru/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"разрешения"</string>
<string name="cancel" msgid="8943320028373963831">"Отмена"</string>
<string name="back" msgid="6249950659061523680">"Назад"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Закрыть"</string>
<string name="available" msgid="6007778121920339498">"Доступно"</string>
<string name="blocked" msgid="9195547604866033708">"Заблокировано"</string>
<string name="on" msgid="280241003226755921">"Включено"</string>
@@ -685,10 +684,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"ОК"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Запрос разрешений заблокирован"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Это приложение запрашивает дополнительные разрешения, которые невозможно предоставить во время трансляции на устройство. Сначала откройте доступ на телефоне."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Для экстренного вызова или сообщения"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Местоположение отправлено экстренным службам"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Это приложение получало доступ к местоположению устройства во время звонка или отправки сообщения на номер экстренной службы. Такое возможно, даже если у приложения нет разрешения на определение местоположения или геолокация отключена на устройстве. "<a href="https://support.google.com/android/answer/9319337">"Подробнее…"</a></string>
</resources>
diff --git a/PermissionController/res/values-si/strings.xml b/PermissionController/res/values-si/strings.xml
index c72db1460..00b2e3a6f 100644
--- a/PermissionController/res/values-si/strings.xml
+++ b/PermissionController/res/values-si/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"අවසර"</string>
<string name="cancel" msgid="8943320028373963831">"අවලංගු කරන්න"</string>
<string name="back" msgid="6249950659061523680">"ආපසු යන්න"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"වසන්න"</string>
<string name="available" msgid="6007778121920339498">"තිබේ"</string>
<string name="blocked" msgid="9195547604866033708">"අවහිරයි"</string>
<string name="on" msgid="280241003226755921">"සක්‍රීය"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"හරි"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"අවසර ඉල්ලීම වළක්වා ඇත"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"මෙම යෙදුම අතිරේක අවසර ඉල්ලා සිටින නමුත්, ප්‍රවාහ කිරීමේ සැසියක අවසර ලබා දිය නොහැක. පළමුව ඔබේ දුරකථනයෙන් අවසරය ලබා දෙන්න."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"හදිසි ඇමතුම් හෝ පෙළ සඳහා"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"ස්ථානය හදිසි සේවා වෙත යවනු ලැබේ"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"මෙම යෙදුම හදිසි ඇමතුම් අංකයකට ඇමතුමක් දෙන හෝ කෙටි පණිවිඩයක් යවන අතරතුර ඔබේ උපාංගයේ ස්ථානයට ප්‍රවේශ විය. යෙදුමට ස්ථාන අවසරයක් නොමැති විට හෝ උපාංග ස්ථානය ක්‍රියා විරහිත විට පවා මෙය සිදු විය හැක. "<a href="https://support.google.com/android/answer/9319337">"තව දැන ගන්න"</a></string>
</resources>
diff --git a/PermissionController/res/values-sq/strings.xml b/PermissionController/res/values-sq/strings.xml
index 7a8b54843..b46cdb5c0 100644
--- a/PermissionController/res/values-sq/strings.xml
+++ b/PermissionController/res/values-sq/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"lejet"</string>
<string name="cancel" msgid="8943320028373963831">"Anulo"</string>
<string name="back" msgid="6249950659061523680">"Pas"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"Mbyll"</string>
<string name="available" msgid="6007778121920339498">"Ofrohet"</string>
<string name="blocked" msgid="9195547604866033708">"Bllokuar"</string>
<string name="on" msgid="280241003226755921">"Aktiv"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"Në rregull"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"Kërkesa për leje është ndaluar"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"Ky aplikacion po kërkon leje shtesë, por lejet nuk mund të jepen në një seancë transmetimi. Fillimisht jep lejen në telefonin tënd."</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"Për telefonatën apo mesazhin me tekst të urgjencës"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"Vendndodhja u dërgua te shërbimet e urgjencës"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"Ky aplikacion u qas te vendndodhja e pajisjes sate gjatë një telefonate apo mesazhi me tekst drejt një numri urgjence. Kjo mund të ndodhë edhe kur aplikacioni nuk ka lejen për vendndodhjen ose kur vendndodhja e pajisjes është joaktive. "<a href="https://support.google.com/android/answer/9319337">"Mëso më shumë"</a></string>
</resources>
diff --git a/PermissionController/res/values-sv/strings.xml b/PermissionController/res/values-sv/strings.xml
index 9ed421d42..18b0263f5 100644
--- a/PermissionController/res/values-sv/strings.xml
+++ b/PermissionController/res/values-sv/strings.xml
@@ -356,7 +356,7 @@
<string name="role_assistant_label" msgid="4727586018198208128">"Digital assistentapp, standard"</string>
<string name="role_assistant_short_label" msgid="3369003713187703399">"Digital assistentapp"</string>
<string name="role_assistant_description" msgid="6622458130459922952">"Med assistentappar kan du få hjälp som baseras på den information som visas på den aktuella skärmen. Vissa appar har stöd för både översikts- och röstinmatningstjänster för att hjälpa dig."</string>
- <string name="role_browser_label" msgid="2877796144554070207">"Standard webbläsarapp"</string>
+ <string name="role_browser_label" msgid="2877796144554070207">"Standard­webbläsarapp"</string>
<string name="role_browser_short_label" msgid="6745009127123292296">"Webbläsarapp"</string>
<string name="role_browser_description" msgid="3465253637499842671">"Appar som visar länkar du trycker på och du använder för att ansluta till internet"</string>
<string name="role_browser_request_title" msgid="2895200507835937192">"Vill du ställa in <xliff:g id="APP_NAME">%1$s</xliff:g> som din standardwebbläsarapp?"</string>
diff --git a/PermissionController/res/values-zh-rCN/strings.xml b/PermissionController/res/values-zh-rCN/strings.xml
index 031937f03..0c77f8035 100644
--- a/PermissionController/res/values-zh-rCN/strings.xml
+++ b/PermissionController/res/values-zh-rCN/strings.xml
@@ -21,8 +21,7 @@
<string name="permission_search_keyword" msgid="1214451577494730543">"权限"</string>
<string name="cancel" msgid="8943320028373963831">"取消"</string>
<string name="back" msgid="6249950659061523680">"返回"</string>
- <!-- no translation found for dialog_close (6840699812532384661) -->
- <skip />
+ <string name="dialog_close" msgid="6840699812532384661">"关闭"</string>
<string name="available" msgid="6007778121920339498">"可用"</string>
<string name="blocked" msgid="9195547604866033708">"已禁用"</string>
<string name="on" msgid="280241003226755921">"已开启"</string>
@@ -683,10 +682,7 @@
<string name="enhanced_confirmation_dialog_ok" msgid="8560373821598619924">"确定"</string>
<string name="permission_grant_dialog_streaming_blocked_title" msgid="8905241017017043649">"权限请求被阻止"</string>
<string name="permission_grant_dialog_streaming_blocked_description" msgid="838165608934085319">"此应用请求获得额外的权限,但在流式传输会话期间无法授予权限。请先在手机上授予相应权限。"</string>
- <!-- no translation found for privacy_dashboard_emergency_location_enforced_attribution_label (5702912511473457693) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_title (849723944428031911) -->
- <skip />
- <!-- no translation found for privacy_dashboard_emergency_location_dialog_description (5815970230573483329) -->
- <skip />
+ <string name="privacy_dashboard_emergency_location_enforced_attribution_label" msgid="5702912511473457693">"用于紧急呼叫或发送紧急短信"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_title" msgid="849723944428031911">"已向应急服务发送位置信息"</string>
+ <string name="privacy_dashboard_emergency_location_dialog_description" msgid="5815970230573483329">"在向紧急电话号码致电或发短信期间,此应用会获取您设备的位置信息。即使此应用没有位置信息权限或设备位置信息服务已关闭,也可能发生此情况。"<a href="https://support.google.com/android/answer/9319337">"了解详情"</a></string>
</resources>
diff --git a/PermissionController/res/values/dimens.xml b/PermissionController/res/values/dimens.xml
index 53d5341fe..32a2d8334 100644
--- a/PermissionController/res/values/dimens.xml
+++ b/PermissionController/res/values/dimens.xml
@@ -70,6 +70,8 @@
<dimen name="location_accuracy_image_size">130dp</dimen>
+ <dimen name="toggle_preference_container_min_width">56dp</dimen>
+
<item name="permission_access_time_dialog_width_scalar" format="float" type="dimen">0.9</item>
<item name="permission_access_time_dialog_height_scalar" format="float" type="dimen">0.7</item>
diff --git a/PermissionController/res/values/overlayable.xml b/PermissionController/res/values/overlayable.xml
index 0cf52ac4a..28de266e4 100644
--- a/PermissionController/res/values/overlayable.xml
+++ b/PermissionController/res/values/overlayable.xml
@@ -328,6 +328,7 @@
<!-- END CAR THEMES -->
<!-- START LAYOUTPREFERENCE -->
+ <!-- {@deprecated Use SettingsLibEntityHeaderTitle.} -->
<item type="style" name="TextAppearance.EntityHeaderTitle" />
<!-- END LAYOUTPREFERENCE -->
@@ -416,6 +417,11 @@
<item type="style" name="EnhancedConfirmationDialogButton" />
<!-- END ENHANCED CONFIRMATION DIALOG -->
+ <item type="style" name="SettingsLibEntityHeader" />
+ <item type="style" name="SettingsLibEntityHeaderContent" />
+ <item type="style" name="SettingsLibEntityHeaderIcon" />
+ <item type="style" name="SettingsLibEntityHeaderTitle" />
+
</policy>
</overlayable>
diff --git a/PermissionController/res/values/strings.xml b/PermissionController/res/values/strings.xml
index e114d69bc..698a9bbb4 100644
--- a/PermissionController/res/values/strings.xml
+++ b/PermissionController/res/values/strings.xml
@@ -2034,4 +2034,13 @@ Allow <xliff:g id="app_name" example="Gmail">%4$s</xliff:g> to upload a bug repo
<!-- Description of the dialog when clicking the app op access entry for EMERGENCY_LOCATION in the privacy dashboard -->
<string name="privacy_dashboard_emergency_location_dialog_description">This app accessed your device\'s location during a call or text to an emergency number. This can happen even when the app doesn\'t have location permission or the device location is off. <a href="https://support.google.com/android/answer/9319337">Learn more</a></string>
<!-- Close button in the pop up dialog when clicking the app op access entry in the privacy dashboard -->
+
+ <!-- Text instructing user to check their paired phone-->
+ <string name="wear_check_your_phone_title">Check your phone</string>
+
+ <!-- Text letting the user to know that companion phone couldn't be reached -->
+ <string name="wear_phone_connection_error">Couldn\'t reach your phone</string>
+
+ <!-- Text asking the user if they want to retry connecting to the paired phone -->
+ <string name="wear_phone_connection_should_retry">Retry?</string>
</resources>
diff --git a/PermissionController/res/values/themes.xml b/PermissionController/res/values/themes.xml
index 2e6af4af1..9aa14a64c 100644
--- a/PermissionController/res/values/themes.xml
+++ b/PermissionController/res/values/themes.xml
@@ -107,6 +107,8 @@
<style name="Theme.DeviceDefault.Dialog.NoActionBar.DayNight" parent="@android:style/Theme.DeviceDefault.Light.Dialog.NoActionBar" />
+ <style name="Theme.DeviceDefault.Dialog.Alert.DayNight" parent="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
+
<!--
TODO(b/309578419): Make activities handle insets properly and then remove this.
-->
@@ -152,7 +154,7 @@
<!-- START ENHANCED CONFIRMATION DIALOG -->
- <style name="Theme.EnhancedConfirmationDialog" parent="@android:style/Theme.DeviceDefault.Dialog.NoActionBar">
+ <style name="Theme.EnhancedConfirmationDialog" parent="@style/Theme.DeviceDefault.Dialog.NoActionBar.DayNight">
<item name="windowNoTitle">true</item>
<item name="android:alertDialogTheme">@style/Theme.EnhancedConfirmationDialogFragment</item>
<item name="android:buttonBarStyle">@style/EnhancedConfirmationDialogButtonBar</item>
@@ -161,7 +163,7 @@
<item name="android:buttonBarNeutralButtonStyle">@style/EnhancedConfirmationDialogButton</item>
</style>
- <style name="Theme.EnhancedConfirmationDialogFragment" parent="@android:style/Theme.DeviceDefault.Dialog.Alert">
+ <style name="Theme.EnhancedConfirmationDialogFragment" parent="@style/Theme.DeviceDefault.Dialog.Alert.DayNight">
<item name="android:buttonBarStyle">@style/EnhancedConfirmationDialogButtonBar</item>
</style>
diff --git a/PermissionController/role-controller/java/com/android/role/controller/compat/AppOpsManagerCompat.java b/PermissionController/role-controller/java/com/android/role/controller/compat/AppOpsManagerCompat.java
index 8e5a768df..82873d185 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/compat/AppOpsManagerCompat.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/compat/AppOpsManagerCompat.java
@@ -17,10 +17,13 @@
package com.android.role.controller.compat;
+import android.annotation.SuppressLint;
import android.app.AppOpsManager;
+import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import com.android.modules.utils.build.SdkLevel;
@@ -29,6 +32,11 @@ import java.util.Objects;
/** Helper for accessing features in {@link AppOpsManager}. */
public class AppOpsManagerCompat {
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @SuppressLint("NewApi")
+ public static final String OPSTR_ACCESS_RESTRICTED_SETTINGS =
+ AppOpsManager.OPSTR_ACCESS_RESTRICTED_SETTINGS;
+
private AppOpsManagerCompat() {}
/**
diff --git a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
index e813b782a..bc6f774ad 100644
--- a/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
+++ b/PermissionController/src/com/android/permissioncontroller/ecm/EnhancedConfirmationDialogActivity.kt
@@ -40,8 +40,10 @@ import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import com.android.modules.utils.build.SdkLevel
import com.android.permissioncontroller.Constants.EXTRA_IS_ECM_IN_APP
+import com.android.permissioncontroller.DeviceUtils
import com.android.permissioncontroller.R
import com.android.permissioncontroller.ecm.EnhancedConfirmationStatsLogUtils.DialogResult
+import com.android.permissioncontroller.permission.ui.wear.WearEnhancedConfirmationDialogFragment
import com.android.permissioncontroller.permission.utils.KotlinUtils
import com.android.permissioncontroller.permission.utils.PermissionMapping
import com.android.permissioncontroller.permission.utils.Utils
@@ -82,9 +84,13 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() {
setClearRestrictionAllowed(packageName, UserHandle.getUserHandleForUid(uid))
val setting = Setting.fromIdentifier(this, settingIdentifier, isEcmInApp)
- val dialogFragment =
+ if (DeviceUtils.isWear(this)) {
+ WearEnhancedConfirmationDialogFragment.newInstance(setting.title, setting.message)
+ .show(supportFragmentManager, WearEnhancedConfirmationDialogFragment.TAG)
+ } else {
EnhancedConfirmationDialogFragment.newInstance(setting.title, setting.message)
- dialogFragment.show(supportFragmentManager, EnhancedConfirmationDialogFragment.TAG)
+ .show(supportFragmentManager, EnhancedConfirmationDialogFragment.TAG)
+ }
}
override fun onSaveInstanceState(outState: Bundle) {
@@ -178,7 +184,7 @@ class EnhancedConfirmationDialogActivity : FragmentActivity() {
}
}
- private fun onDialogResult(dialogResult: DialogResult) {
+ fun onDialogResult(dialogResult: DialogResult) {
this.dialogResult = dialogResult
setResult(
RESULT_OK,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
index eb78414f9..e3deb58a7 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/PermissionControllerServiceImpl.java
@@ -861,6 +861,7 @@ public final class PermissionControllerServiceImpl extends PermissionControllerL
group.setSelfRevoked();
group.persistChanges(false);
}
+ Log.d(LOG_TAG, "Self revoked permissions: " + String.join(",", permissions));
getMainExecutor().execute(callback);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
index 58536b796..715e3823d 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/service/v34/SafetyLabelChangesJobService.kt
@@ -111,10 +111,6 @@ class SafetyLabelChangesJobService : JobService() {
Log.i(LOG_TAG, "onReceive: Safety label change notifications are not enabled.")
return
}
- if (KotlinUtils.safetyLabelChangesJobServiceKillSwitch()) {
- Log.i(LOG_TAG, "onReceive: kill switch is set.")
- return
- }
if (isContextInProfileUser(receiverContext)) {
Log.i(
LOG_TAG,
@@ -174,10 +170,6 @@ class SafetyLabelChangesJobService : JobService() {
Log.w(LOG_TAG, "Not starting job: safety label change notifications are not enabled.")
return false
}
- if (KotlinUtils.safetyLabelChangesJobServiceKillSwitch()) {
- Log.i(LOG_TAG, "Not starting job: kill switch is set.")
- return false
- }
when (params.jobId) {
SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID -> {
dispatchDetectUpdatesJob(params)
@@ -490,8 +482,7 @@ class SafetyLabelChangesJobService : JobService() {
private suspend fun getNumberOfAppsWithDataSharingChanged(): Int {
val appDataSharingUpdates =
AppDataSharingUpdatesLiveData(PermissionControllerApplication.get())
- .getInitializedValue()
- ?: return 0
+ .getInitializedValue() ?: return 0
return appDataSharingUpdates
.map { appDataSharingUpdate ->
@@ -523,8 +514,7 @@ class SafetyLabelChangesJobService : JobService() {
}
?.keys
?.filter { packageUser: Pair<String, UserHandle> -> packageUser.first == packageName }
- ?.map { packageUser: Pair<String, UserHandle> -> packageUser.second }
- ?: listOf()
+ ?.map { packageUser: Pair<String, UserHandle> -> packageUser.second } ?: listOf()
}
private fun AppDataSharingUpdate.containsLocationCategoryUpdate() =
@@ -660,9 +650,7 @@ class SafetyLabelChangesJobService : JobService() {
SAFETY_LABEL_CHANGES_DETECT_UPDATES_JOB_ID,
ComponentName(context, SafetyLabelChangesJobService::class.java)
)
- .setRequiresDeviceIdle(
- KotlinUtils.runSafetyLabelChangesJobOnlyWhenDeviceIdle()
- )
+ .setRequiresDeviceIdle(true)
.build()
val result = jobScheduler.schedule(job)
if (result != JobScheduler.RESULT_SUCCESS) {
@@ -693,9 +681,7 @@ class SafetyLabelChangesJobService : JobService() {
SAFETY_LABEL_CHANGES_PERIODIC_NOTIFICATION_JOB_ID,
ComponentName(context, SafetyLabelChangesJobService::class.java)
)
- .setRequiresDeviceIdle(
- KotlinUtils.runSafetyLabelChangesJobOnlyWhenDeviceIdle()
- )
+ .setRequiresDeviceIdle(true)
.setPeriodic(KotlinUtils.getSafetyLabelChangesJobIntervalMillis())
.setPersisted(true)
.build()
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
index 1f30572ad..04fd11561 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/auto/AutoAppPermissionFragment.java
@@ -22,6 +22,8 @@ import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_ALWAYS;
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW_FOREGROUND;
import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__DENY;
+import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__GRANT_FINE_LOCATION;
+import static com.android.permissioncontroller.PermissionControllerStatsLog.APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__REVOKE_FINE_LOCATION;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_INTERACTED;
import static com.android.permissioncontroller.permission.ui.ManagePermissionsActivity.EXTRA_RESULT_PERMISSION_RESULT;
@@ -42,6 +44,7 @@ import android.text.BidiFormatter;
import android.util.Log;
import android.view.View;
import android.widget.RadioButton;
+import android.widget.Switch;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -95,6 +98,9 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
private TwoStatePreference mForegroundOnlyPermissionPreference;
@NonNull
private TwoStatePreference mDenyPermissionPreference;
+
+ @NonNull
+ private TwoStatePreference mToggleFineLocationPreference;
@NonNull
private AutoTwoTargetPreference mDetailsPreference;
@@ -127,9 +133,9 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
* Returns a new {@link AutoAppPermissionFragment}.
*
* @param packageName the package name for which the permission is being changed
- * @param permName the name of the permission being changed
- * @param groupName the name of the permission group being changed
- * @param userHandle the user for which the permission is being changed
+ * @param permName the name of the permission being changed
+ * @param groupName the name of the permission group being changed
+ * @param userHandle the user for which the permission is being changed
*/
@NonNull
public static AutoAppPermissionFragment newInstance(@NonNull String packageName,
@@ -157,6 +163,7 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
mPackageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
mPermGroupName = getArguments().getString(Intent.EXTRA_PERMISSION_GROUP_NAME);
if (mPermGroupName == null) {
@@ -214,6 +221,29 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
mDenyPermissionPreference.setTitle(R.string.app_permission_button_deny);
permissionSelector.addPreference(mDenyPermissionPreference);
+
+ Log.w(LOG_TAG, "enableCoarseFineLocationPromptForAaos flag set to: "
+ + Flags.enableCoarseFineLocationPromptForAaos());
+ if (Flags.enableCoarseFineLocationPromptForAaos()) {
+ mToggleFineLocationPreference = new SelectedSwitchPermissionPreference(
+ requireContext());
+ mToggleFineLocationPreference.setTitle(R.string.app_permission_location_accuracy);
+ mToggleFineLocationPreference.setSummary(
+ R.string.app_permission_location_accuracy_subtitle);
+ permissionSelector.addPreference(mToggleFineLocationPreference);
+
+ mToggleFineLocationPreference.setOnPreferenceClickListener(v -> {
+ if (mToggleFineLocationPreference.isChecked()) {
+ requestChange(ChangeRequest.GRANT_FINE_LOCATION,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__GRANT_FINE_LOCATION);
+ } else {
+ requestChange(ChangeRequest.REVOKE_FINE_LOCATION,
+ APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__REVOKE_FINE_LOCATION);
+ }
+ return true;
+ });
+ }
+
mAllowPermissionPreference.setOnPreferenceClickListener(v -> {
checkOnlyOneButtonOverride(AppPermissionViewModel.ButtonType.ALLOW);
setResult(GrantPermissionsViewHandler.GRANTED_ALWAYS);
@@ -244,6 +274,8 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
});
mDetailsPreference = new AutoTwoTargetPreference(requireContext());
+ // If the details are updated, setDetail will update the visibility
+ mDetailsPreference.setVisible(false);
screen.addPreference(mDetailsPreference);
}
@@ -294,6 +326,16 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
}
}
}
+
+ if (Flags.enableCoarseFineLocationPromptForAaos()) {
+ mViewModel.getButtonStateLiveData().observe(this, buttonState -> {
+ AppPermissionViewModel.ButtonState locationAccuracyState = buttonState.get(
+ AppPermissionViewModel.ButtonType.LOCATION_ACCURACY);
+ mToggleFineLocationPreference.setVisible(locationAccuracyState.isShown());
+ mToggleFineLocationPreference.setChecked(locationAccuracyState.isChecked());
+ mToggleFineLocationPreference.setEnabled(locationAccuracyState.isEnabled());
+ });
+ }
}
@Override
@@ -498,6 +540,7 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
} else {
mDetailsPreference.setSummary(detailResIds.getFirst());
}
+ mDetailsPreference.setVisible(true);
}
/**
@@ -552,6 +595,26 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
}
}
+ private static class SelectedSwitchPermissionPreference extends TwoStatePreference {
+
+ SelectedSwitchPermissionPreference(Context context) {
+ super(context, null,
+ TypedArrayUtils.getAttr(context, androidx.preference.R.attr.preferenceStyle,
+ android.R.attr.preferenceStyle));
+ setPersistent(false);
+ setLayoutResource(R.layout.car_switch_button_preference);
+ setWidgetLayoutResource(R.layout.switch_button_preference_widget);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ Switch switchButton = (Switch) holder.findViewById(R.id.location_accuracy_switch);
+ switchButton.setChecked(isChecked());
+ }
+ }
+
/**
* A dialog warning the user that they are about to deny a permission that was granted by
* default.
@@ -564,7 +627,7 @@ public class AutoAppPermissionFragment extends AutoSettingsFrameFragment
+ ".arg.changeRequest";
private static final String BUTTON = ConfirmDialog.class.getName()
+ ".arg.button";
- private static int sCode = APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW;
+ private static int sCode = APP_PERMISSION_FRAGMENT_ACTION_REPORTED__BUTTON_PRESSED__ALLOW;
@NonNull
@Override
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TEST_MAPPING b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TEST_MAPPING
new file mode 100644
index 000000000..1a74fb208
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/television/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "tv-postsubmit": [
+ {
+ "name": "PermissionUiTestCases",
+ "options": [
+ {"include-filter": "com.android.permissioncontroller.permissionui.ui.television"},
+ {"exclude-annotation": "org.junit.Ignore"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ },
+ {
+ "name": "CtsPermissionUiTestCases",
+ "options": [
+ {"include-filter": "android.permissionui.cts.CameraMicIndicatorsPermissionTest"},
+ {"exclude-annotation": "org.junit.Ignore"}
+ ]
+ }
+ ]
+} \ No newline at end of file
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 3936e54d4..5e6929cfb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionFragment.kt
@@ -125,15 +125,14 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment {
val permGroupName =
arguments?.getString(Intent.EXTRA_PERMISSION_GROUP_NAME)
?: arguments?.getString(Intent.EXTRA_PERMISSION_NAME)
- ?: throw RuntimeException("Permission name must not be null.")
+ ?: throw RuntimeException("Permission name must not be null.")
val isStorageGroup = permGroupName == Manifest.permission_group.STORAGE
val user =
arguments?.let {
BundleCompat.getParcelable(it, Intent.EXTRA_USER, UserHandle::class.java)
- }
- ?: UserHandle.SYSTEM
+ } ?: UserHandle.SYSTEM
val permGroupLabel = getPermGroupLabel(activity, permGroupName).toString()
val sessionId = arguments?.getLong(EXTRA_SESSION_ID) ?: Constants.INVALID_SESSION_ID
@@ -233,6 +232,8 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment {
confirmDialogViewModel.showAdvancedConfirmDialogLiveData.value = false
}
+ val onDisabledAllowButtonTap: () -> Unit = { viewModel.handleDisabledAllowButton(this) }
+
return ComposeView(activity).apply {
setContent {
WearPermissionTheme {
@@ -246,7 +247,8 @@ class WearAppPermissionFragment : Fragment(), ConfirmDialogShowingFragment {
onConfirmDialogOkButtonClick,
onConfirmDialogCancelButtonClick,
onAdvancedConfirmDialogOkButtonClick,
- onAdvancedConfirmDialogCancelButtonClick
+ onAdvancedConfirmDialogCancelButtonClick,
+ onDisabledAllowButtonTap
)
}
}
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 ccbd51f7d..202ad49bb 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearAppPermissionScreen.kt
@@ -25,6 +25,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.res.stringResource
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.material.ToggleChipDefaults
import com.android.permissioncontroller.R
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel
import com.android.permissioncontroller.permission.ui.model.AppPermissionViewModel.ButtonState
@@ -35,6 +36,7 @@ import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter
import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
+import com.android.permissioncontroller.permission.ui.wear.elements.toggleChipDisabledColors
import com.android.permissioncontroller.permission.ui.wear.model.AppPermissionConfirmDialogViewModel
import com.android.permissioncontroller.permission.ui.wear.model.ConfirmDialogArgs
import com.android.settingslib.RestrictedLockUtils
@@ -50,7 +52,8 @@ fun WearAppPermissionScreen(
onConfirmDialogOkButtonClick: (ConfirmDialogArgs) -> Unit,
onConfirmDialogCancelButtonClick: () -> Unit,
onAdvancedConfirmDialogOkButtonClick: (AdvancedConfirmDialogArgs) -> Unit,
- onAdvancedConfirmDialogCancelButtonClick: () -> Unit
+ onAdvancedConfirmDialogCancelButtonClick: () -> Unit,
+ onDisabledAllowButtonClick: () -> Unit
) {
val buttonState = viewModel.buttonStateLiveData.observeAsState(null)
val detailResIds = viewModel.detailResIdLiveData.observeAsState(null)
@@ -70,6 +73,7 @@ fun WearAppPermissionScreen(
onLocationSwitchChanged,
onGrantedStateChanged,
onFooterClicked,
+ onDisabledAllowButtonClick
)
ConfirmDialog(
showDialog = showConfirmDialog.value,
@@ -98,7 +102,8 @@ internal fun WearAppPermissionContent(
isLoading: Boolean,
onLocationSwitchChanged: (Boolean) -> Unit,
onGrantedStateChanged: (ButtonType, Boolean) -> Unit,
- onFooterClicked: (RestrictedLockUtils.EnforcedAdmin) -> Unit
+ onFooterClicked: (RestrictedLockUtils.EnforcedAdmin) -> Unit,
+ onDisabledAllowButtonClick: () -> Unit
) {
ScrollableScreen(title = title, isLoading = isLoading) {
buttonState?.get(ButtonType.LOCATION_ACCURACY)?.let {
@@ -121,11 +126,20 @@ internal fun WearAppPermissionContent(
item {
ToggleChip(
checked = it.isChecked,
- enabled = it.isEnabled,
+ colors =
+ if (it.isEnabled) {
+ ToggleChipDefaults.toggleChipColors()
+ } else {
+ toggleChipDisabledColors()
+ },
label = labelsByButton(buttonType),
toggleControl = ToggleChipToggleControl.Radio,
onCheckedChanged = { checked ->
- onGrantedStateChanged(buttonType, checked)
+ if (it.isEnabled) {
+ onGrantedStateChanged(buttonType, checked)
+ } else {
+ onDisabledAllowButtonClick()
+ }
},
labelMaxLine = Integer.MAX_VALUE
)
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt
new file mode 100644
index 000000000..c978f5968
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationDialogFragment.kt
@@ -0,0 +1,73 @@
+/*
+ * 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
+
+import android.content.Context
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.compose.ui.platform.ComposeView
+import androidx.fragment.app.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
+
+class WearEnhancedConfirmationDialogFragment : DialogFragment() {
+ private lateinit var enhancedConfirmationDialogActivity: EnhancedConfirmationDialogActivity
+ private val viewModel: WearEnhancedConfirmationViewModel by viewModels()
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ enhancedConfirmationDialogActivity = context as EnhancedConfirmationDialogActivity
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val title =
+ arguments?.getString(KEY_TITLE) ?: throw RuntimeException("ECM Title can't be null")
+ val message =
+ arguments?.getCharSequence(KEY_MESSAGE)?.apply {
+ viewModel.stripLearnMoreLinkFrom(this)
+ } ?: throw RuntimeException("ECM Message can't be null")
+
+ return ComposeView(enhancedConfirmationDialogActivity).apply {
+ setContent {
+ WearPermissionTheme { WearEnhancedConfirmationScreen(viewModel, title, message) }
+ }
+ }
+ }
+
+ companion object {
+ const val TAG = "WearEnhancedConfirmationDialogFragment"
+ private const val KEY_TITLE = "KEY_TITLE"
+ private const val KEY_MESSAGE = "KEY_MESSAGE"
+
+ fun newInstance(title: String? = null, message: CharSequence? = null) =
+ WearEnhancedConfirmationDialogFragment().apply {
+ arguments =
+ Bundle().apply {
+ putString(KEY_TITLE, title)
+ putCharSequence(KEY_MESSAGE, message)
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt
new file mode 100644
index 000000000..349ec1dfe
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/WearEnhancedConfirmationScreen.kt
@@ -0,0 +1,146 @@
+/*
+ * 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
+
+import android.app.Activity
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.fragment.app.FragmentActivity
+import androidx.wear.compose.foundation.SwipeToDismissValue
+import androidx.wear.compose.foundation.lazy.ScalingLazyListState
+import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
+import androidx.wear.compose.material.ChipDefaults
+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.AlertDialog
+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.Chip
+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.model.WearEnhancedConfirmationViewModel
+import com.android.permissioncontroller.permission.ui.wear.model.WearEnhancedConfirmationViewModel.ScreenState
+
+@Composable
+fun WearEnhancedConfirmationScreen(
+ viewModel: WearEnhancedConfirmationViewModel,
+ title: String?,
+ message: CharSequence?,
+) {
+ var dismissed by remember { mutableStateOf(false) }
+ val context = LocalContext.current
+ val ecmScreenState = remember { viewModel.screenState }
+ val activity = context.findActivity()
+
+ val state = rememberSwipeToDismissBoxState()
+
+ LaunchedEffect(state.currentValue) {
+ if (state.currentValue == SwipeToDismissValue.Dismissed) {
+ dismiss(activity)
+ dismissed = true
+ state.snapTo(SwipeToDismissValue.Default)
+ }
+ }
+
+ fun dismiss(activity: Activity) {
+ if (activity is FragmentActivity) {
+ if (!activity.supportFragmentManager.popBackStackImmediate()) {
+ activity.finish()
+ }
+ } else {
+ activity.finish()
+ }
+ }
+
+ @Composable
+ fun ShowECMRestrictionDialog() =
+ ScrollableScreen(
+ showTimeText = false,
+ title = title,
+ subtitle = message,
+ image = R.drawable.ic_android_security_privacy,
+ content = {
+ item {
+ Chip(
+ label = stringResource(R.string.enhanced_confirmation_dialog_ok),
+ onClick = { dismiss(activity) },
+ modifier = Modifier.fillMaxWidth(),
+ textColor = MaterialTheme.colors.surface,
+ colors = ChipDefaults.primaryChipColors()
+ )
+ }
+ item {
+ Chip(
+ label = stringResource(R.string.enhanced_confirmation_dialog_learn_more),
+ onClick = { viewModel.openUriOnPhone(context) },
+ modifier = Modifier.fillMaxWidth(),
+ )
+ }
+ }
+ )
+
+ @Composable
+ fun ShowCheckYourPhoneDialog(state: CheckYourPhoneState) =
+ CheckYourPhoneScreen(
+ title = stringResource(id = R.string.wear_check_your_phone_title),
+ state = state
+ )
+
+ @Composable
+ fun ShowRemoteConnectionErrorDialog() =
+ AlertDialog(
+ title = stringResource(R.string.wear_phone_connection_error),
+ message = stringResource(R.string.wear_phone_connection_should_retry),
+ iconRes = R.drawable.ic_error,
+ showDialog = true,
+ okButtonIcon = R.drawable.ic_refresh,
+ onOKButtonClick = { viewModel.openUriOnPhone(context) },
+ onCancelButtonClick = { dismiss(activity) },
+ scalingLazyListState = ScalingLazyListState(1)
+ )
+
+ SwipeToDismissBox(state = state) { isBackground ->
+ if (isBackground || dismissed) {
+ Box(modifier = Modifier.fillMaxSize()) {
+ CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
+ }
+ } else {
+ when (ecmScreenState.value) {
+ ScreenState.SHOW_RESTRICTION_DIALOG -> ShowECMRestrictionDialog()
+ ScreenState.SHOW_CONNECTION_IN_PROGRESS -> ShowCheckYourPhoneDialog(InProgress)
+ ScreenState.SHOW_CONNECTION_ERROR -> ShowRemoteConnectionErrorDialog()
+ ScreenState.SHOW_CONNECTION_SUCCESS -> ShowCheckYourPhoneDialog(Success)
+ }
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt
index aa04cfad8..77fbc811f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/AlertDialog.kt
@@ -17,11 +17,15 @@
package com.android.permissioncontroller.permission.ui.wear.elements
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.rememberTextMeasurer
@@ -52,6 +56,8 @@ import com.android.permissioncontroller.permission.ui.wear.elements.layout.remem
fun AlertDialog(
message: String,
iconRes: Int? = null,
+ okButtonIcon: Any = Icons.Default.Check,
+ cancelButtonIcon: Any = Icons.Default.Close,
onCancelButtonClick: () -> Unit,
onOKButtonClick: () -> Unit,
showDialog: Boolean,
@@ -61,9 +67,13 @@ fun AlertDialog(
okButtonContentDescription: String = stringResource(android.R.string.ok),
cancelButtonContentDescription: String = stringResource(android.R.string.cancel)
) {
+ val focusManager = LocalFocusManager.current
Dialog(
showDialog = showDialog,
- onDismissRequest = onCancelButtonClick,
+ onDismissRequest = {
+ focusManager.clearFocus()
+ onCancelButtonClick()
+ },
scrollState = scalingLazyListState,
modifier = modifier
) {
@@ -71,6 +81,8 @@ fun AlertDialog(
title = title,
icon = { AlertIcon(iconRes) },
message = message,
+ okButtonIcon = okButtonIcon,
+ cancelButtonIcon = cancelButtonIcon,
onCancel = onCancelButtonClick,
onOk = onOKButtonClick,
okButtonContentDescription = okButtonContentDescription,
@@ -89,6 +101,7 @@ fun AlertDialog(
fun SingleButtonAlertDialog(
message: String,
iconRes: Int? = null,
+ okButtonIcon: Any = Icons.Default.Check,
onButtonClick: () -> Unit,
showDialog: Boolean,
scalingLazyListState: ScalingLazyListState,
@@ -106,6 +119,7 @@ fun SingleButtonAlertDialog(
title = title,
icon = { AlertIcon(iconRes) },
message = message,
+ okButtonIcon = okButtonIcon,
onOk = onButtonClick,
okButtonContentDescription = buttonContentDescription
)
@@ -113,12 +127,14 @@ fun SingleButtonAlertDialog(
}
@Composable
-public fun AlertContent(
+fun AlertContent(
onCancel: (() -> Unit)? = null,
onOk: (() -> Unit)? = null,
icon: @Composable (() -> Unit)? = null,
title: String? = null,
message: String? = null,
+ okButtonIcon: Any = Icons.Default.Check,
+ cancelButtonIcon: Any = Icons.Default.Close,
okButtonContentDescription: String = stringResource(android.R.string.ok),
cancelButtonContentDescription: String = stringResource(android.R.string.cancel),
state: ScalingLazyColumnState =
@@ -187,6 +203,8 @@ public fun AlertContent(
content = content,
onOk = onOk,
onCancel = onCancel,
+ okButtonIcon = okButtonIcon,
+ cancelButtonIcon = cancelButtonIcon,
okButtonContentDescription = okButtonContentDescription,
cancelButtonContentDescription = cancelButtonContentDescription,
state = state,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt
new file mode 100644
index 000000000..59376b8fa
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/CheckYourPhone.kt
@@ -0,0 +1,124 @@
+/*
+ * 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 android.content.res.Configuration
+import androidx.compose.foundation.layout.Arrangement
+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.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalConfiguration
+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.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
+private const val SIDE_PADDING_SCREEN_PERCENTAGE = 0.052f
+private const val TEXT_PADDING_SCREEN_PERCENTAGE = 0.0416f
+
+enum class CheckYourPhoneState {
+ InProgress,
+ 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(
+ title: String,
+ state: CheckYourPhoneState,
+ modifier: Modifier = Modifier,
+ 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
+ val textPadding =
+ if (isLarge) (configuration.screenHeightDp * TEXT_PADDING_SCREEN_PERCENTAGE).dp else 0.dp
+
+ Scaffold {
+ Column(
+ modifier =
+ modifier
+ .fillMaxSize()
+ .padding(
+ top = topPadding,
+ bottom = bottomPadding,
+ start = sidePadding,
+ end = sidePadding,
+ ),
+ ) {
+ Column(
+ modifier = Modifier.fillMaxWidth().weight(1f).padding(horizontal = textPadding),
+ verticalArrangement = Arrangement.Center,
+ ) {
+ Text(
+ text = title,
+ modifier = Modifier.fillMaxWidth().align(Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.title3.copy(fontWeight = FontWeight.W600),
+ )
+
+ if (message != null) {
+ Text(
+ text = message,
+ modifier =
+ Modifier.padding(top = 20.dp)
+ .fillMaxWidth()
+ .align(Alignment.CenterHorizontally),
+ textAlign = TextAlign.Center,
+ )
+ }
+ }
+ 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)
+ )
+ }
+ }
+ }
+}
+
+/** 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/RemoteConnectionProgressIndicator.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/RemoteConnectionProgressIndicator.kt
new file mode 100644
index 000000000..244e7e3fd
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/RemoteConnectionProgressIndicator.kt
@@ -0,0 +1,75 @@
+/*
+ * 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/elements/ResponsiveDialog.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ResponsiveDialog.kt
index cf828b91d..e1e869f71 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ResponsiveDialog.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ResponsiveDialog.kt
@@ -36,9 +36,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
@@ -63,6 +63,8 @@ fun ResponsiveDialogContent(
icon: @Composable (() -> Unit)? = null,
title: @Composable (() -> Unit)? = null,
message: @Composable (() -> Unit)? = null,
+ okButtonIcon: Any = Icons.Default.Check,
+ cancelButtonIcon: Any = Icons.Default.Close,
onOk: (() -> Unit)? = null,
onCancel: (() -> Unit)? = null,
okButtonContentDescription: String = stringResource(android.R.string.ok),
@@ -104,7 +106,8 @@ fun ResponsiveDialogContent(
title?.let {
item {
CompositionLocalProvider(
- LocalTextStyle provides MaterialTheme.typography.title3,
+ LocalTextStyle provides
+ MaterialTheme.typography.title3.copy(fontWeight = FontWeight.W600),
) {
Box(
Modifier.fillMaxWidth(titleMaxWidthFraction)
@@ -151,7 +154,7 @@ fun ResponsiveDialogContent(
) {
onCancel?.let {
ResponsiveButton(
- icon = Icons.Default.Close,
+ icon = cancelButtonIcon,
cancelButtonContentDescription,
onClick = it,
buttonWidth,
@@ -160,7 +163,7 @@ fun ResponsiveDialogContent(
}
onOk?.let {
ResponsiveButton(
- icon = Icons.Default.Check,
+ icon = okButtonIcon,
okButtonContentDescription,
onClick = it,
buttonWidth,
@@ -176,7 +179,7 @@ fun ResponsiveDialogContent(
@Composable
private fun ResponsiveButton(
- icon: ImageVector,
+ icon: Any,
contentDescription: String,
onClick: () -> Unit,
buttonWidth: Dp,
@@ -186,7 +189,7 @@ private fun ResponsiveButton(
label = {
Box(Modifier.fillMaxWidth()) {
Icon(
- imageVector = icon,
+ icon = icon,
contentDescription = contentDescription,
modifier =
Modifier.size(ButtonDefaults.DefaultIconSize).align(Alignment.Center),
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
index 717cf9528..1700c719f 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ScrollableScreen.kt
@@ -135,12 +135,13 @@ internal fun Scaffold(
titleTestTag: String? = null,
subtitleTestTag: String? = null,
) {
+ val itemsSpacedBy = 4.dp
val screenWidth = LocalConfiguration.current.screenWidthDp
val screenHeight = LocalConfiguration.current.screenHeightDp
val scrollContentHorizontalPadding = (screenWidth * 0.052).dp
val titleHorizontalPadding = (screenWidth * 0.0884).dp
val subtitleHorizontalPadding = (screenWidth * 0.0416).dp
- val scrollContentTopPadding = (screenHeight * 0.1456).dp
+ val scrollContentTopPadding = (screenHeight * 0.1456).dp - itemsSpacedBy
val scrollContentBottomPadding = (screenHeight * 0.3636).dp
val titleBottomPadding =
if (subtitle == null) {
@@ -218,6 +219,7 @@ internal fun Scaffold(
bottom = scrollContentBottomPadding
)
) {
+ staticItem()
image?.let {
val imageModifier = Modifier.size(24.dp)
when (image) {
@@ -284,6 +286,26 @@ internal fun Scaffold(
}
}
+private fun ScalingLazyListScope.staticItem() {
+ /*
+ This empty item helps to ensure accurate scroll offset calculation. If auto centering is enabled
+ initial item's(first item for us) center matches the center of the screen. Scroll offset is 0 at
+ that point.
+
+ if auto centering is not enabled, initial item will start at the top of the screen with the
+ scroll offset equal to ScreenHeight/2 - scrollContentTopPadding - firstItemHeight/2.
+
+ We need to this offset value to properly move time text.That is the scroll-away offset of the
+ Time Text is equal to the scroll offset of the list at initial position.
+
+ It is easier to calculate if we know the values of ScreenHeight, ScrollContentTopPadding and
+ FirstItem's height. ScreenHeight and ScrollContentPadding are constants but height of the
+ FirstItem depends on the content. Instead of measuring the height, we can simplify the
+ calculation with an empty item with 0dp height.
+ */
+ item {}
+}
+
@Composable
private fun RequestFocusOnResume(focusRequester: FocusRequester) {
val lifecycleOwner = LocalLifecycleOwner.current
@@ -308,8 +330,7 @@ internal fun getBackStackEntryCount(activity: Activity): Int {
return if (activity is FragmentActivity) {
activity.supportFragmentManager.primaryNavigationFragment
?.childFragmentManager
- ?.backStackEntryCount
- ?: 0
+ ?.backStackEntryCount ?: 0
} else {
0
}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
index fe1e75d67..a21a9d015 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/elements/ToggleChip.kt
@@ -30,6 +30,8 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.style.TextAlign
@@ -51,7 +53,7 @@ import com.android.permissioncontroller.R
* - a convenient way of providing an icon and setting the icon to be mirrored in RTL mode;
*/
@Composable
-public fun ToggleChip(
+fun ToggleChip(
checked: Boolean,
onCheckedChanged: (Boolean) -> Unit,
label: String,
@@ -127,6 +129,13 @@ public fun ToggleChip(
}
}
+ val semanticsRole =
+ when (toggleControl) {
+ ToggleChipToggleControl.Switch -> Role.Switch
+ ToggleChipToggleControl.Radio -> Role.RadioButton
+ ToggleChipToggleControl.Checkbox -> Role.Checkbox
+ }
+
val stateDescriptionSemantics =
stringResource(
if (checked) {
@@ -141,7 +150,10 @@ public fun ToggleChip(
label = labelParam,
toggleControl = toggleControlParam,
modifier =
- modifier.fillMaxWidth().semantics { stateDescription = stateDescriptionSemantics },
+ modifier.fillMaxWidth().semantics {
+ role = semanticsRole
+ stateDescription = stateDescriptionSemantics
+ },
appIcon = iconParam,
secondaryLabel = secondaryLabelParam,
colors = colors,
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/RemoteActivityHelper.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/RemoteActivityHelper.kt
new file mode 100644
index 000000000..3debe7bd3
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/RemoteActivityHelper.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.model
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.os.Parcel
+import android.os.ResultReceiver
+import kotlin.coroutines.Continuation
+import kotlin.coroutines.resume
+import kotlinx.coroutines.suspendCancellableCoroutine
+
+/*This class can be removed when the androidx library is available in Gerrit */
+class RemoteActivityHelper(val context: Context) {
+
+ companion object {
+ @SuppressWarnings("ActionValue")
+ private const val ACTION_REMOTE_INTENT: String =
+ "com.google.android.wearable.intent.action.REMOTE_INTENT"
+
+ private const val EXTRA_INTENT: String = "com.google.android.wearable.intent.extra.INTENT"
+
+ private const val EXTRA_RESULT_RECEIVER: String =
+ "com.google.android.wearable.intent.extra.RESULT_RECEIVER"
+
+ private const val RESULT_OK: Int = 0
+
+ private const val DEFAULT_PACKAGE = "com.google.android.wearable.app"
+
+ private fun getResultReceiverForSending(receiver: ResultReceiver): ResultReceiver {
+ val parcel = Parcel.obtain()
+ receiver.writeToParcel(parcel, 0)
+ parcel.setDataPosition(0)
+ val receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel)
+ parcel.recycle()
+ return receiverForSending
+ }
+ }
+
+ suspend fun startRemoteActivity(targetIntent: Intent): Boolean =
+ suspendCancellableCoroutine { cont ->
+ require(Intent.ACTION_VIEW == targetIntent.action) {
+ "Only ${Intent.ACTION_VIEW} action is currently supported for starting a" +
+ " remote activity"
+ }
+ requireNotNull(targetIntent.data) {
+ "Data Uri is required when starting a remote activity"
+ }
+ require(targetIntent.categories?.contains(Intent.CATEGORY_BROWSABLE) == true) {
+ "The category ${Intent.CATEGORY_BROWSABLE} must be present on the intent"
+ }
+ val remoteResultReceiver = RemoteIntentResultReceiver(cont)
+ val remoteIntent =
+ Intent(ACTION_REMOTE_INTENT).apply {
+ setPackage(DEFAULT_PACKAGE)
+ putExtra(EXTRA_INTENT, targetIntent)
+ putExtra(
+ EXTRA_RESULT_RECEIVER,
+ getResultReceiverForSending(remoteResultReceiver)
+ )
+ }
+ context.sendBroadcast(remoteIntent)
+ }
+
+ private class RemoteIntentResultReceiver(val continuation: Continuation<Boolean>) :
+ ResultReceiver(null) {
+ override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
+ continuation.resume(resultCode == RESULT_OK)
+ }
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearEnhancedConfirmationViewModel.kt b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearEnhancedConfirmationViewModel.kt
new file mode 100644
index 000000000..2a7df54ca
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/wear/model/WearEnhancedConfirmationViewModel.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.model
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.text.SpannableStringBuilder
+import android.text.style.URLSpan
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.android.permissioncontroller.R
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class WearEnhancedConfirmationViewModel : ViewModel() {
+ enum class ScreenState {
+ SHOW_RESTRICTION_DIALOG,
+ SHOW_CONNECTION_IN_PROGRESS,
+ SHOW_CONNECTION_ERROR,
+ SHOW_CONNECTION_SUCCESS
+ }
+
+ private val mutableScreenState: MutableState<ScreenState> =
+ mutableStateOf(ScreenState.SHOW_RESTRICTION_DIALOG)
+ val screenState: State<ScreenState> = mutableScreenState
+
+ private fun getLearnMoreUri(context: Context) =
+ Uri.parse(context.getString(R.string.help_url_action_disabled_by_restricted_settings))
+
+ fun openUriOnPhone(context: Context) =
+ viewModelScope.launch {
+ val uri = getLearnMoreUri(context)
+ mutableScreenState.value = ScreenState.SHOW_CONNECTION_IN_PROGRESS
+ val target =
+ Intent(Intent.ACTION_VIEW).setData(uri).addCategory(Intent.CATEGORY_BROWSABLE)
+ val isSuccessful =
+ withContext(Dispatchers.IO) {
+ RemoteActivityHelper(context).startRemoteActivity(target)
+ }
+ mutableScreenState.value =
+ if (isSuccessful) {
+ ScreenState.SHOW_CONNECTION_SUCCESS
+ } else {
+ ScreenState.SHOW_CONNECTION_ERROR
+ }
+ }
+
+ fun stripLearnMoreLinkFrom(message: CharSequence): CharSequence {
+ val text = SpannableStringBuilder.valueOf(message)
+ text.getSpans(0, message.length, URLSpan::class.java).map {
+ val spanStart = text.getSpanStart(it)
+ val spanEnd = text.getSpanEnd(it)
+ text.removeSpan(it)
+ text.delete(spanStart, spanEnd)
+ }
+ return text
+ }
+}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
index b822aa541..e55cf9f92 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt
@@ -164,10 +164,6 @@ object KotlinUtils {
private const val PROPERTY_SAFETY_LABEL_CHANGES_JOB_RUN_WHEN_IDLE =
"safety_label_changes_job_run_when_idle"
- /** Whether the kill switch is set for [SafetyLabelChangesJobService]. */
- private const val PROPERTY_SAFETY_LABEL_CHANGES_JOB_SERVICE_KILL_SWITCH =
- "safety_label_changes_job_service_kill_switch"
-
data class Quadruple<out A, out B, out C, out D>(
val first: A,
val second: B,
@@ -278,20 +274,6 @@ object KotlinUtils {
!DeviceUtils.isWear(context)
}
- /**
- * Whether the kill switch is set for [SafetyLabelChangesJobService]. If {@code true}, the
- * service is effectively disabled and will not run or schedule any jobs.
- */
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
- fun safetyLabelChangesJobServiceKillSwitch(): Boolean {
- return SdkLevel.isAtLeastU() &&
- DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_SAFETY_LABEL_CHANGES_JOB_SERVICE_KILL_SWITCH,
- false
- )
- }
-
/** How often the safety label changes job will run. */
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
fun getSafetyLabelChangesJobIntervalMillis(): Long {
@@ -302,16 +284,6 @@ object KotlinUtils {
)
}
- /** Whether the safety label changes job should only be run when the device is idle. */
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE, codename = "UpsideDownCake")
- fun runSafetyLabelChangesJobOnlyWhenDeviceIdle(): Boolean {
- return DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PRIVACY,
- PROPERTY_SAFETY_LABEL_CHANGES_JOB_RUN_WHEN_IDLE,
- true
- )
- }
-
/**
* Given a Map, and a List, determines which elements are in the list, but not the map, and vice
* versa. Used primarily for determining which liveDatas are already being watched, and which
diff --git a/flags/flags.aconfig b/flags/flags.aconfig
index a81de8144..2dd34e5ff 100644
--- a/flags/flags.aconfig
+++ b/flags/flags.aconfig
@@ -45,3 +45,21 @@ flag {
bug: "327489942"
is_fixed_read_only: true
}
+
+flag {
+ name: "enable_coarse_fine_location_prompt_for_aaos"
+ is_exported: true
+ namespace: "permissions"
+ description: "Feature flag to enable downgrading to coarse location on Automotive"
+ bug: "346369736"
+ is_fixed_read_only: true
+}
+
+flag {
+ name: "livevdata_refactor_permission_timeline_enabled"
+ is_exported: true
+ namespace: "permissions"
+ description: "This flag is used to enable modern app architecture implementation for timeline page"
+ bug: "354234946"
+ is_fixed_read_only: true
+}
diff --git a/service/java/com/android/ecm/EnhancedConfirmationService.java b/service/java/com/android/ecm/EnhancedConfirmationService.java
index 6e6501234..708884e85 100644
--- a/service/java/com/android/ecm/EnhancedConfirmationService.java
+++ b/service/java/com/android/ecm/EnhancedConfirmationService.java
@@ -348,7 +348,6 @@ public class EnhancedConfirmationService extends SystemService {
private boolean isSettingEcmProtected(@NonNull String settingIdentifier) {
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
- || mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
|| mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
return false;
}
diff --git a/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java b/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
index 4c8eb1df1..1fb0aaa2b 100644
--- a/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
+++ b/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
@@ -238,6 +238,7 @@ public class RuntimePermissionsPersistenceImpl implements RuntimePermissionsPers
}
File reserveFile = getReserveCopyFile(user);
+ reserveFile.delete();
try (FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(reserveFile)) {
FileUtils.copy(in, out);
diff --git a/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index f308304b5..220a8440b 100644
--- a/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -215,6 +215,7 @@ public class RolesPersistenceImpl implements RolesPersistence {
}
File reserveFile = getReserveCopyFile(user);
+ reserveFile.delete();
try (FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(reserveFile)) {
FileUtils.copy(in, out);
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
index b92287bb3..815dcd6b1 100644
--- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -8063,7 +8063,8 @@
<p>Not for use by third-party applications. -->
<permission
android:name="android.permission.CAPTURE_CONSENTLESS_BUGREPORT_DELEGATED_CONSENT"
- android:protectionLevel="signature|privileged" />
+ android:protectionLevel="signature|privileged"
+ android:featureFlag="android.os.allow_consentless_bugreport_delegated_consent" />
<!-- @SystemApi Allows to call APIs that log process lifecycle events
@hide -->
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
index 244d18ca6..fdc13b3af 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/BaseUsePermissionTest.kt
@@ -51,7 +51,6 @@ import com.android.compatibility.common.util.SystemUtil
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
-import com.android.compatibility.common.util.UiAutomatorUtils2
import com.android.modules.utils.build.SdkLevel
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
@@ -145,6 +144,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
"grant_dialog_button_deny_and_dont_ask_again"
const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT = "grant_dialog_button_no_upgrade"
+ const val ECM_ALERT_DIALOG_OK_BUTTON_TEXT = "enhanced_confirmation_dialog_ok"
const val ALERT_DIALOG_MESSAGE = "android:id/message"
const val ALERT_DIALOG_OK_BUTTON = "android:id/button1"
const val APP_PERMISSION_RATIONALE_CONTAINER_VIEW =
@@ -369,8 +369,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
// dialog
callWithShellPermissionIdentity {
context.packageManager.resolveActivity(finishOnCreateIntent, PackageManager.MATCH_ALL)
- }
- ?: return
+ } ?: return
// Start the test app, and expect the targetSDK warning dialog
context.startActivity(finishOnCreateIntent)
@@ -486,31 +485,19 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
}
protected fun installPackageWithInstallSourceAndNoMetadataFromStore(apkName: String) {
- installPackageViaSession(
- apkName,
- packageSource = PACKAGE_SOURCE_STORE
- )
+ installPackageViaSession(apkName, packageSource = PACKAGE_SOURCE_STORE)
}
protected fun installPackageWithInstallSourceAndNoMetadataFromLocalFile(apkName: String) {
- installPackageViaSession(
- apkName,
- packageSource = PACKAGE_SOURCE_LOCAL_FILE
- )
+ installPackageViaSession(apkName, packageSource = PACKAGE_SOURCE_LOCAL_FILE)
}
protected fun installPackageWithInstallSourceAndNoMetadataFromDownloadedFile(apkName: String) {
- installPackageViaSession(
- apkName,
- packageSource = PACKAGE_SOURCE_DOWNLOADED_FILE
- )
+ installPackageViaSession(apkName, packageSource = PACKAGE_SOURCE_DOWNLOADED_FILE)
}
protected fun installPackageWithInstallSourceAndNoMetadataFromOther(apkName: String) {
- installPackageViaSession(
- apkName,
- packageSource = PACKAGE_SOURCE_OTHER
- )
+ installPackageViaSession(apkName, packageSource = PACKAGE_SOURCE_OTHER)
}
protected fun installPackageWithInstallSourceAndInvalidMetadata(apkName: String) {
@@ -893,7 +880,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
protected fun clickPermissionRequestDenyButton() {
if (isAutomotive) {
- scrollToBottom();
+ scrollToBottom()
clickAndWaitForWindowTransition(
By.text(getPermissionControllerString(DENY_BUTTON_TEXT))
)
@@ -960,9 +947,10 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
uiDevice.click(x.toInt(), y.toInt())
waitForIdleLong()
val nextScreenNode: AccessibilityNodeInfo? =
- findAccessibilityNodeInfosByTextForSurfaceView(
- uiAutomation.rootInActiveWindow,
- "All the time")
+ findAccessibilityNodeInfosByTextForSurfaceView(
+ uiAutomation.rootInActiveWindow,
+ "All the time"
+ )
if (nextScreenNode != null) {
clickedOnLink = true
break
@@ -973,7 +961,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
protected fun clickPermissionRequestDenyAndDontAskAgainButton() {
if (isAutomotive) {
- scrollToBottom();
+ scrollToBottom()
clickAndWaitForWindowTransition(
By.text(getPermissionControllerString(DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT))
)
@@ -1335,6 +1323,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
android.Manifest.permission.ACCESS_BACKGROUND_LOCATION -> true
else -> false
}
+
private fun showsAllowPhotosButton(permission: String): Boolean {
if (!isPhotoPickerPermissionPromptEnabled()) {
return false
@@ -1451,4 +1440,19 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
}
}
}
+
+ protected fun clickECMAlertDialogOKButton(waitForWindowTransition: Boolean = !isWatch) {
+ var action = { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
+ if (isWatch) {
+ val okButtonText =
+ getPermissionControllerResString(ECM_ALERT_DIALOG_OK_BUTTON_TEXT) ?: "OK"
+ action = { click(By.text(okButtonText), TIMEOUT_MILLIS) }
+ }
+
+ if (waitForWindowTransition) {
+ doAndWaitForWindowTransition { action() }
+ } else {
+ action()
+ }
+ }
}
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt
index 7bcd8a911..c20803706 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/CameraMicIndicatorsPermissionTest.kt
@@ -87,8 +87,7 @@ private const val PRIVACY_ITEM_ID = "com.android.systemui:id/privacy_item"
private const val INDICATORS_FLAG = "camera_mic_icons_enabled"
private const val WEAR_MIC_LABEL = "Microphone"
private const val PERMISSION_INDICATORS_NOT_PRESENT = 162547999L
-private const val IDLE_TIMEOUT_MILLIS: Long = 1000
-private const val UNEXPECTED_TIMEOUT_MILLIS = 1000L
+private const val IDLE_TIMEOUT_MILLIS: Long = 2000
private const val TIMEOUT_MILLIS: Long = 20000
private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator"
private const val MIC_LABEL_NAME = "microphone_toggle_label_qs"
@@ -456,6 +455,13 @@ class CameraMicIndicatorsPermissionTest : StsExtraBusinessLogicTestCase {
} else {
useMic
}
+ if (!micInUse && !useCamera) {
+ // We're asserting the indicator is gone. Wait up to IDLE_TIMEOUT after the quick
+ // settings is opened to see if we find the indicator, so we don't automatically
+ // assert the indicator is gone, just because we didn't open quick settings fast
+ // enough.
+ UiAutomatorUtils2.waitFindObjectOrNull(By.res(PRIVACY_CHIP_ID), IDLE_TIMEOUT_MILLIS)
+ }
assertPrivacyChipAndIndicatorsPresent(
micInUse,
useCamera,
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
index 0453f8cf1..f7d20b866 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/EnhancedConfirmationManagerTest.kt
@@ -62,23 +62,22 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@Before
- fun assumeNotAutoTvOrWear() {
+ fun assumeNotAutoOrTv() {
Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
- Assume.assumeFalse(
- packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
- )
- Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH))
+ Assume.assumeFalse(packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
}
@RequiresFlagsEnabled(Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED)
@Test
fun installedAppStartsWithModeDefault() {
installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_LATEST)
- runWithShellPermissionIdentity {
- assertEquals(
- getAppEcmState(context, appOpsManager, APP_PACKAGE_NAME),
- AppOpsManager.MODE_DEFAULT
- )
+ eventually {
+ runWithShellPermissionIdentity {
+ assertEquals(
+ getAppEcmState(context, appOpsManager, APP_PACKAGE_NAME),
+ AppOpsManager.MODE_DEFAULT
+ )
+ }
}
}
@@ -113,6 +112,14 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
@Test
fun givenExplicitlyRestrictedAppThenIsRestrictedFromProtectedSetting() {
installPackageWithInstallSourceAndMetadataFromStore(APP_APK_NAME_LATEST)
+ eventually {
+ runWithShellPermissionIdentity {
+ assertEquals(
+ getAppEcmState(context, appOpsManager, APP_PACKAGE_NAME),
+ AppOpsManager.MODE_DEFAULT
+ )
+ }
+ }
runWithShellPermissionIdentity {
eventually { assertFalse(ecm.isRestricted(APP_PACKAGE_NAME, PROTECTED_SETTING)) }
setAppEcmState(context, appOpsManager, APP_PACKAGE_NAME, AppOpsManager.MODE_ERRORED)
@@ -174,7 +181,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
)
requestAppPermissionsAndAssertResult(*permissionAndExpectedGrantResults) {
- click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS)
+ clickECMAlertDialogOKButton(waitForWindowTransition = false)
}
assertTrue(isClearRestrictionAllowed(APP_PACKAGE_NAME))
@@ -201,8 +208,8 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
GROUP_2_PERMISSION_2_RESTRICTED to false,
waitForWindowTransition = false
) {
- doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
- doAndWaitForWindowTransition { clickPermissionRequestDenyButton() }
+ clickECMAlertDialogOKButton()
+ clickPermissionRequestDenyButton()
}
assertTrue(isClearRestrictionAllowed(APP_PACKAGE_NAME))
@@ -211,7 +218,7 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
GROUP_3_PERMISSION_2_UNRESTRICTED to true,
waitForWindowTransition = false
) {
- doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ clickPermissionRequestAllowForegroundButton()
}
assertTrue(isClearRestrictionAllowed(APP_PACKAGE_NAME))
}
@@ -228,8 +235,8 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
GROUP_2_PERMISSION_1_RESTRICTED to false,
waitForWindowTransition = false
) {
- doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
- doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ clickECMAlertDialogOKButton()
+ clickPermissionRequestAllowForegroundButton()
}
assertTrue(isClearRestrictionAllowed(APP_PACKAGE_NAME))
}
@@ -246,8 +253,8 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
GROUP_2_PERMISSION_1_RESTRICTED to false,
waitForWindowTransition = false
) {
- doAndWaitForWindowTransition { click(By.res(ALERT_DIALOG_OK_BUTTON), TIMEOUT_MILLIS) }
- doAndWaitForWindowTransition { clickPermissionRequestAllowForegroundButton() }
+ clickECMAlertDialogOKButton()
+ clickPermissionRequestAllowForegroundButton()
}
assertTrue(isClearRestrictionAllowed(APP_PACKAGE_NAME))
}
@@ -259,7 +266,17 @@ class EnhancedConfirmationManagerTest : BaseUsePermissionTest() {
private fun assertNoEcmDialogShown() {
assertNull(
"expected to not see dialog",
- waitFindObjectOrNull(By.res(ALERT_DIALOG_OK_BUTTON), UNEXPECTED_TIMEOUT_MILLIS.toLong())
+ if (isWatch) {
+ waitFindObjectOrNull(
+ By.text(getPermissionControllerString(ECM_ALERT_DIALOG_OK_BUTTON_TEXT)),
+ UNEXPECTED_TIMEOUT_MILLIS.toLong()
+ )
+ } else {
+ waitFindObjectOrNull(
+ By.res(ALERT_DIALOG_OK_BUTTON),
+ UNEXPECTED_TIMEOUT_MILLIS.toLong()
+ )
+ }
)
}