summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PermissionController/res/values-ar/strings.xml4
-rw-r--r--PermissionController/res/values-cs/strings.xml2
-rw-r--r--PermissionController/res/values-hu/strings.xml2
-rw-r--r--PermissionController/res/values-ja/strings.xml4
-rw-r--r--PermissionController/res/values-mk/strings.xml2
-rw-r--r--PermissionController/res/values-nb/strings.xml2
-rw-r--r--PermissionController/res/values-pl/strings.xml2
-rw-r--r--PermissionController/res/values-ru-v33/strings.xml2
-rw-r--r--PermissionController/res/xml/roles.xml2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/model/Role.java24
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java2
-rw-r--r--PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java12
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/Role.md7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java28
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java26
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java8
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java7
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationPreference.java6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java6
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/behavior/v35/WalletRoleUiBehavior.java53
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java17
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt16
-rw-r--r--PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt19
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt13
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/IssueUiData.kt27
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt41
-rw-r--r--PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt24
-rw-r--r--PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt212
-rw-r--r--PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt7
-rw-r--r--PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt7
-rw-r--r--PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt7
-rw-r--r--SafetyCenter/OWNERS1
-rw-r--r--SafetyCenter/Resources/res/values-mk-v35/strings.xml2
-rw-r--r--SafetyCenter/Resources/res/values-mk/strings.xml4
-rw-r--r--service/java/com/android/permission/util/UserUtils.java30
-rw-r--r--service/java/com/android/role/RoleService.java3
-rw-r--r--service/java/com/android/safetycenter/UserProfileGroup.java5
-rw-r--r--tests/cts/permissionpolicy/res/raw/android_manifest.xml12
-rw-r--r--tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt36
-rw-r--r--tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt53
-rw-r--r--tests/cts/safetycenter/AndroidTest.xml4
-rw-r--r--tests/functional/safetycenter/multiusers/AndroidTest.xml4
-rw-r--r--tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml4
-rw-r--r--tests/functional/safetycenter/singleuser/AndroidTest.xml4
-rw-r--r--tests/functional/safetycenter/subpages/AndroidTest.xml4
-rw-r--r--tests/hostside/safetycenter/AndroidTest.xml4
51 files changed, 607 insertions, 237 deletions
diff --git a/PermissionController/res/values-ar/strings.xml b/PermissionController/res/values-ar/strings.xml
index 5381d11b4..e22ec0182 100644
--- a/PermissionController/res/values-ar/strings.xml
+++ b/PermissionController/res/values-ar/strings.xml
@@ -475,7 +475,7 @@
<string name="permgrouprequest_device_aware_storage_isolated" msgid="6463062962458809752">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الصور والوسائط على &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
<string name="permgrouprequest_contacts" msgid="8391550064551053695">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى جهات الاتصال؟"</string>
<string name="permgrouprequest_device_aware_contacts" msgid="731025863972535928">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى جهات اتصالك على &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
- <string name="permgrouprequest_location" msgid="6990232580121067883">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي لهذا الجهاز؟"</string>
+ <string name="permgrouprequest_location" msgid="6990232580121067883">"‏هل مطلوب السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي لهذا الجهاز؟"</string>
<string name="permgrouprequest_device_aware_location" msgid="6075412127429878638">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي الخاص بـ &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
<string name="permgrouprequestdetail_location" msgid="2635935335778429894">"لن يكون بإمكان التطبيق الوصول إلى الموقع الجغرافي إلا عند استخدامك لهذا التطبيق."</string>
<string name="permgroupbackgroundrequest_location" msgid="1085680897265734809">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الموقع الجغرافي لهذا الجهاز؟"</string>
@@ -495,7 +495,7 @@
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"تقريبي"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى التقويم؟"</string>
<string name="permgrouprequest_device_aware_calendar" msgid="7161929851377463612">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى تقويمك على &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإرسال رسائل SMS وعرضها؟"</string>
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"‏هل مطلوب السماح لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> بإرسال رسائل SMS وعرضها؟"</string>
<string name="permgrouprequest_device_aware_sms" msgid="6639977653040502291">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بإرسال الرسائل القصيرة وعرضها على &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الصور والوسائط والملفات على جهازك؟"</string>
<string name="permgrouprequest_device_aware_storage" msgid="6933251810928606636">"‏هل تريد السماح لـ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالوصول إلى الصور والوسائط والملفات على &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;؟"</string>
diff --git a/PermissionController/res/values-cs/strings.xml b/PermissionController/res/values-cs/strings.xml
index 8ca485fbe..a48d5afb9 100644
--- a/PermissionController/res/values-cs/strings.xml
+++ b/PermissionController/res/values-cs/strings.xml
@@ -383,7 +383,7 @@
<string name="role_emergency_search_keywords" msgid="1920007722599213358">"v případě nouze"</string>
<string name="role_home_label" msgid="3871847846649769412">"Výchozí aplikace pro domácnost"</string>
<string name="role_home_short_label" msgid="8544733747952272337">"Vstupní aplikace"</string>
- <string name="role_home_description" msgid="7997371519626556675">"Aplikace (tzv. spouštěče), které nahrazují plochu na zařízení Android a dávají vám přístup\\nk obsahu a funkcím zařízení."</string>
+ <string name="role_home_description" msgid="7997371519626556675">"Aplikace (tzv. spouštěče), které nahrazují plochu na zařízení Android a dávají vám přístup k obsahu a funkcím zařízení."</string>
<string name="role_home_request_title" msgid="738136983453341081">"Nastavit <xliff:g id="APP_NAME">%1$s</xliff:g> jako výchozí aplikaci pro domácnost?"</string>
<string name="role_home_request_description" msgid="2658833966716057673">"Není potřeba žádné oprávnění"</string>
<string name="role_home_search_keywords" msgid="3830755001192666285">"spouštěč"</string>
diff --git a/PermissionController/res/values-hu/strings.xml b/PermissionController/res/values-hu/strings.xml
index 997dc71e2..038f0161f 100644
--- a/PermissionController/res/values-hu/strings.xml
+++ b/PermissionController/res/values-hu/strings.xml
@@ -495,7 +495,7 @@
<string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"Hozzávetőleges"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen a naptárhoz?"</string>
<string name="permgrouprequest_device_aware_calendar" msgid="7161929851377463612">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen a naptárához ezen az eszközön: &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>’s&lt;/b&gt;?"</string>
- <string name="permgrouprequest_sms" msgid="5672063688745420991">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy SMS-eket küldhessen és tekinthessen meg?"</string>
+ <string name="permgrouprequest_sms" msgid="5672063688745420991">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára SMS-ek küldését és megtekintését?"</string>
<string name="permgrouprequest_device_aware_sms" msgid="6639977653040502291">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára az SMS-ek küldését és megtekintését ezen az eszközön: &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;?"</string>
<string name="permgrouprequest_storage" msgid="8717773092518621602">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hozzáférjen az eszközön tárolt fotókhoz, médiatartalmakhoz és fájlokhoz?"</string>
<string name="permgrouprequest_device_aware_storage" msgid="6933251810928606636">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy fotókhoz, médiatartalmakhoz és fájlokhoz férjen hozzá ezen az eszközön: &lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;?"</string>
diff --git a/PermissionController/res/values-ja/strings.xml b/PermissionController/res/values-ja/strings.xml
index 43e204b69..0be93d464 100644
--- a/PermissionController/res/values-ja/strings.xml
+++ b/PermissionController/res/values-ja/strings.xml
@@ -491,8 +491,8 @@
<string name="permgrouprequest_device_aware_fineupgrade" msgid="4453775952305587571">"&lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;の位置情報に対する &lt;b&gt;<xliff:g id="APP_NAME">&lt;b&gt;%1$s&lt;/b&gt;</xliff:g>&lt;/b&gt; のアクセス権を「おおよそ」から「正確」に変更しますか?"</string>
<string name="permgrouprequest_coarselocation" msgid="7244605063736425232">"このデバイスのおおよその位置情報へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequest_device_aware_coarselocation" msgid="8367540370912066757">"&lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;のおおよその位置情報へのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
- <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"正確"</string>
- <string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"おおよそ"</string>
+ <string name="permgrouprequest_finelocation_imagetext" msgid="1313062433398914334">"正確な位置"</string>
+ <string name="permgrouprequest_coarselocation_imagetext" msgid="8650605041483025297">"おおよその位置"</string>
<string name="permgrouprequest_calendar" msgid="1493150855673603806">"カレンダーへのアクセスを「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
<string name="permgrouprequest_device_aware_calendar" msgid="7161929851377463612">"&lt;b&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/b&gt;内のカレンダーへのアクセスを &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
<string name="permgrouprequest_sms" msgid="5672063688745420991">"SMS メッセージの送信と表示を「&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;」に許可しますか?"</string>
diff --git a/PermissionController/res/values-mk/strings.xml b/PermissionController/res/values-mk/strings.xml
index 5f2735642..d8ba89c77 100644
--- a/PermissionController/res/values-mk/strings.xml
+++ b/PermissionController/res/values-mk/strings.xml
@@ -628,7 +628,7 @@
<string name="safety_center_background_location_access_reminder_summary" msgid="7431657777510537658">"Апликацијава може секогаш да пристапува до вашата локација, дури и кога е затворена.\n\nНа одредени апликации за безбедност и итни случаи им е потребен пристап до вашата локација во заднината за правилно да функционираат."</string>
<string name="safety_center_background_location_access_revoked" msgid="6972274943343442213">"Пристапот е променет"</string>
<string name="safety_center_view_recent_location_access" msgid="3524391299490678243">"Погледнете го неодамнешното користење на локацијата"</string>
- <string name="privacy_controls_title" msgid="7605929972256835199">"Контроли на приватноста"</string>
+ <string name="privacy_controls_title" msgid="7605929972256835199">"Контроли за приватност"</string>
<string name="camera_toggle_title" msgid="1251201397431837666">"Пристап до камерата"</string>
<string name="mic_toggle_title" msgid="2649991093496110162">"Пристап до микрофонот"</string>
<string name="perm_toggle_description" msgid="7801326363741451379">"За апликации и услуги"</string>
diff --git a/PermissionController/res/values-nb/strings.xml b/PermissionController/res/values-nb/strings.xml
index e2930ac8a..3835d7573 100644
--- a/PermissionController/res/values-nb/strings.xml
+++ b/PermissionController/res/values-nb/strings.xml
@@ -443,7 +443,7 @@
<string name="default_app_recommended" msgid="5669584821778942909">"Optimalisert for enheten"</string>
<string name="default_app_others" msgid="7793029848126079876">"Andre"</string>
<string name="default_app_none" msgid="9084592086808194457">"Ingen"</string>
- <string name="default_app_system_default" msgid="6218386768175513760">"(System-&amp;shy;standard)"</string>
+ <string name="default_app_system_default" msgid="6218386768175513760">"(System-&amp;#173;standard)"</string>
<string name="default_app_no_apps" msgid="115720991680586885">"Ingen apper"</string>
<string name="default_payment_app_other_nfc_services" msgid="5957633798695758917">"Andre NFC-tjenester"</string>
<string name="car_default_app_selected" msgid="5416420830430644174">"Valgt"</string>
diff --git a/PermissionController/res/values-pl/strings.xml b/PermissionController/res/values-pl/strings.xml
index 8316ac98c..0aefe4a69 100644
--- a/PermissionController/res/values-pl/strings.xml
+++ b/PermissionController/res/values-pl/strings.xml
@@ -348,7 +348,7 @@
<string name="no_apps_allowed" msgid="7718822655254468631">"Nie zezwolono żadnym aplikacjom"</string>
<string name="no_apps_allowed_full" msgid="8011716991498934104">"Brak aplikacji z uprawnieniami dla wszystkich plików"</string>
<string name="no_apps_allowed_scoped" msgid="4908850477787659501">"Brak aplikacji z uprawnieniami tylko dla multimediów"</string>
- <string name="no_apps_denied" msgid="7663435886986784743">"Nie zabroniono dostępu żadnym aplikacjom"</string>
+ <string name="no_apps_denied" msgid="7663435886986784743">"Nie odmówiono dostępu żadnym aplikacjom"</string>
<string name="car_permission_selected" msgid="180837028920791596">"Wybrana"</string>
<string name="settings" msgid="5409109923158713323">"Ustawienia"</string>
<string name="accessibility_service_dialog_title_single" msgid="7956432823014102366">"Usługa <xliff:g id="SERVICE_NAME">%s</xliff:g> ma pełny dostęp do urządzenia"</string>
diff --git a/PermissionController/res/values-ru-v33/strings.xml b/PermissionController/res/values-ru-v33/strings.xml
index b45662712..5506ccd97 100644
--- a/PermissionController/res/values-ru-v33/strings.xml
+++ b/PermissionController/res/values-ru-v33/strings.xml
@@ -41,7 +41,7 @@
<string name="safety_center_qs_privacy_control" msgid="1160682635058529673">"Переключатель: <xliff:g id="PRIVACY_CONTROL_TITLE">%1$s</xliff:g> (<xliff:g id="PRIVACY_CONTROL_STATUS">%2$s</xliff:g>)"</string>
<string name="safety_center_qs_toggle_action" msgid="5920465736488119255">"Переключатель"</string>
<string name="safety_center_qs_open_action" msgid="2760200829912423728">"Открыть"</string>
- <string name="safety_center_review_settings_button" msgid="938981137942443930">"Перейти в настройки"</string>
+ <string name="safety_center_review_settings_button" msgid="938981137942443930">"Открыть настройки"</string>
<string name="safety_center_gear_label" msgid="5175877094379694098">"Настройки"</string>
<string name="safety_center_info_label" msgid="8993181584061825412">"Информация"</string>
</resources>
diff --git a/PermissionController/res/xml/roles.xml b/PermissionController/res/xml/roles.xml
index 0f9ff7112..4ba524462 100644
--- a/PermissionController/res/xml/roles.xml
+++ b/PermissionController/res/xml/roles.xml
@@ -902,6 +902,8 @@
<permission name="android.permission.READ_SMS" minSdkVersion="33" />
<permission name="android.permission.READ_PEOPLE_DATA" />
<permission name="android.permission.READ_GLOBAL_APP_SEARCH_DATA" />
+ <permission name="android.permission.READ_BLOCKED_NUMBERS"
+ featureFlag="android.permission.flags.Flags.grantReadBlockedNumbersToSystemUiIntelligence" />
</permissions>
</role>
diff --git a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
index 1b7617b0d..6a7251563 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/model/Role.java
@@ -26,7 +26,6 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
-import android.content.pm.Signature;
import android.content.res.Resources;
import android.os.Build;
import android.os.UserHandle;
@@ -505,8 +504,14 @@ public class Role {
&& Build.VERSION.SDK_INT <= mMaxSdkVersion;
}
- public boolean isStatic() {
- return mStatic;
+ /**
+ * Check whether this role is static, which may change due to bypassing qualification.
+ *
+ * @param context the {@code Context} to retrieve system services
+ * @return whether this role is static
+ */
+ public boolean isStatic(@NonNull Context context) {
+ return mStatic && !isBypassingQualification(context);
}
/**
@@ -621,6 +626,12 @@ public class Role {
return mAllowBypassingQualification;
}
+ private boolean isBypassingQualification(@NonNull Context context) {
+ RoleManager roleManager = context.getSystemService(RoleManager.class);
+ return shouldAllowBypassingQualification(context)
+ && RoleManagerCompat.isBypassingRoleQualification(roleManager);
+ }
+
/**
* Check whether a package is qualified for this role, i.e. whether it contains all the required
* components (plus meeting some other general restrictions).
@@ -633,9 +644,7 @@ public class Role {
*/
public boolean isPackageQualifiedAsUser(@NonNull String packageName, @NonNull UserHandle user,
@NonNull Context context) {
- RoleManager roleManager = context.getSystemService(RoleManager.class);
- if (shouldAllowBypassingQualification(context)
- && RoleManagerCompat.isBypassingRoleQualification(roleManager)) {
+ if (isBypassingQualification(context)) {
return true;
}
@@ -1107,7 +1116,8 @@ public class Role {
// all users
List<UserHandle> profiles =
(crossUserRoleUxBugfixEnabled && getExclusivity() == EXCLUSIVITY_PROFILE_GROUP)
- ? UserUtils.getUserProfiles(context, true) : List.of(user);
+ ? UserUtils.getUserProfiles(user, context, true)
+ : List.of(user);
final int profilesSize = profiles.size();
for (int i = 0; i < profilesSize; i++) {
UserHandle profile = profiles.get(i);
diff --git a/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java
index d00fd47af..1a0c83ab8 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java
@@ -173,7 +173,7 @@ public class RoleControllerServiceImpl extends RoleControllerService {
// or fallback holders, if any.
currentPackageNames = mUserRoleManager.getRoleHolders(roleName);
currentPackageNamesSize = currentPackageNames.size();
- boolean isStaticRole = role.isStatic();
+ boolean isStaticRole = role.isStatic(mContext);
if (currentPackageNamesSize == 0 || isStaticRole) {
List<String> packageNamesToAdd = null;
if (addedRoleNames.contains(roleName) || isStaticRole) {
diff --git a/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java b/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java
index 00c05b17c..41233a23e 100644
--- a/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java
+++ b/PermissionController/role-controller/java/com/android/role/controller/util/UserUtils.java
@@ -139,14 +139,16 @@ public final class UserUtils {
/**
* Returns all the enabled user profiles on the device
*
+ * @param user the {@link UserHandle} to get profiles for
* @param context the {@link Context}
* @param excludePrivate {@code true} to exclude private profiles from returned list of users
*/
@NonNull
- public static List<UserHandle> getUserProfiles(@NonNull Context context,
- boolean excludePrivate) {
- UserManager userManager = context.getSystemService(UserManager.class);
- List<UserHandle> profiles = userManager.getUserProfiles();
+ public static List<UserHandle> getUserProfiles(@NonNull UserHandle user,
+ @NonNull Context context, boolean excludePrivate) {
+ Context userContext = getUserContext(context, user);
+ UserManager userUserManager = userContext.getSystemService(UserManager.class);
+ List<UserHandle> profiles = userUserManager.getUserProfiles();
if (!excludePrivate) {
return profiles;
}
@@ -154,7 +156,7 @@ public final class UserUtils {
final int profilesSize = profiles.size();
for (int i = 0; i < profilesSize; i++) {
UserHandle profile = profiles.get(i);
- if (!isPrivateProfile(profile, context)) {
+ if (!isPrivateProfile(profile, userContext)) {
filteredProfiles.add(profile);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/Role.md b/PermissionController/src/com/android/permissioncontroller/role/Role.md
index 8d995d557..29a184190 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/Role.md
+++ b/PermissionController/src/com/android/permissioncontroller/role/Role.md
@@ -55,14 +55,13 @@ apps, separated by a colon (`:`) with the package name, for instance
receive short text messages, photos, videos, and more". For default apps, this string will appear in
the default app detail page as a footer. This attribute is required if the role is `visible`.
- `exclusive`: Whether the role is exclusive. If a role is exclusive, at most one application is
-allowed to be its holder.
+allowed to be its holder. This attribute is being deprecated and `exclusivity` should be used.
- `exclusivity`: Whether the role is exclusive and what type of exclusivity behavior it has. A role
can have exclusivity of `none`, `user`, or `profileGroup`.
- `none`: Role allows multiple holders
- `user`: Role allows at most one holder within each user
- - `profileGroup`: (SDK 36+ only, fallsback to `user` on lower SDK) Role allows at most one holder
-within a profile group (e.g. full user and work
-profile)
+ - `profileGroup`: (SDK 36+ only, falls back to `user` on lower SDK) Role allows at most one holder
+within a profile group (e.g. full user and work profile)
- `fallBackToDefaultHolder`: Whether the role should fall back to the default holder. This attribute
is optional and defaults to `false`.
- `featureFlag`: Optional feature flag for the role be available, as the fully qualified name of
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
index 268633c4f..814a312c6 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppChildFragment.java
@@ -16,6 +16,8 @@
package com.android.permissioncontroller.role.ui;
+import static com.android.permissioncontroller.PermissionControllerStatsLog.ROLE_SETTINGS_FRAGMENT_ACTION_REPORTED;
+
import android.app.Activity;
import android.app.role.RoleManager;
import android.content.Context;
@@ -41,6 +43,7 @@ import androidx.preference.TwoStatePreference;
import com.android.modules.utils.build.SdkLevel;
import com.android.permission.flags.Flags;
+import com.android.permissioncontroller.PermissionControllerStatsLog;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.role.utils.PackageUtils;
@@ -48,6 +51,7 @@ import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils;
import com.android.permissioncontroller.role.utils.SettingsCompat;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
+import com.android.settingslib.utils.applications.AppUtils;
import java.util.List;
import java.util.Objects;
@@ -77,8 +81,8 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat
DefaultAppChildFragment.class.getName() + ".preference.OTHER_NFC_SERVICES";
private static final String PREFERENCE_EXTRA_PACKAGE_NAME =
DefaultAppChildFragment.class.getName() + ".extra.PACKAGE_NAME";
- private static final String PREFERENCE_EXTRA_USER = DefaultAppChildFragment.class.getName()
- + ".extra.USER";
+ private static final String PREFERENCE_EXTRA_UID = DefaultAppChildFragment.class.getName()
+ + ".extra.UID";
@NonNull
private String mRoleName;
@@ -302,10 +306,13 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat
// the `NONE` item passes a null applicationinfo object. NFC uses a different preference
// method for adding, and a different onclick method
if (applicationInfo != null) {
+ UserHandle user = UserHandle.getUserHandleForUid(applicationInfo.uid);
+ roleApplicationPreference.setContentDescription(
+ AppUtils.getAppContentDescription(
+ context, applicationInfo.packageName, user.getIdentifier()));
Bundle extras = preference.getExtras();
extras.putString(PREFERENCE_EXTRA_PACKAGE_NAME, applicationInfo.packageName);
- extras.putParcelable(PREFERENCE_EXTRA_USER,
- UserHandle.getUserHandleForUid(applicationInfo.uid));
+ extras.putInt(PREFERENCE_EXTRA_UID, applicationInfo.uid);
}
} else {
preference = roleApplicationPreference.asTwoStatePreference();
@@ -348,24 +355,25 @@ public class DefaultAppChildFragment<PF extends PreferenceFragmentCompat
} else {
String packageName =
preference.getExtras().getString(PREFERENCE_EXTRA_PACKAGE_NAME);
- UserHandle user =
- preference.getExtras().getParcelable(PREFERENCE_EXTRA_USER);
+ int uid = preference.getExtras().getInt(PREFERENCE_EXTRA_UID);
CharSequence confirmationMessage =
RoleUiBehaviorUtils.getConfirmationMessage(mRole, packageName,
requireContext());
if (confirmationMessage != null) {
- DefaultAppConfirmationDialogFragment.show(packageName, user, confirmationMessage,
+ DefaultAppConfirmationDialogFragment.show(packageName, uid, confirmationMessage,
this);
} else {
- setDefaultApp(packageName, user);
+ setDefaultApp(packageName, uid);
}
}
return true;
}
@Override
- public void setDefaultApp(@NonNull String packageName, @NonNull UserHandle user) {
- mViewModel.setDefaultApp(packageName, user);
+ public void setDefaultApp(@NonNull String packageName, int uid) {
+ PermissionControllerStatsLog.write(
+ ROLE_SETTINGS_FRAGMENT_ACTION_REPORTED, uid, packageName, mRoleName);
+ mViewModel.setDefaultApp(packageName, UserHandle.getUserHandleForUid(uid));
}
private void addNonPaymentNfcServicesPreference(@NonNull PreferenceScreen preferenceScreen,
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java
index 5f399a0b8..9a9606291 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppConfirmationDialogFragment.java
@@ -20,11 +20,9 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
-import android.os.UserHandle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.os.BundleCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
@@ -34,27 +32,27 @@ import androidx.fragment.app.Fragment;
public class DefaultAppConfirmationDialogFragment extends DialogFragment {
private String mPackageName;
- private UserHandle mUser;
+ private int mUid;
private CharSequence mMessage;
/**
* Create a new instance of this fragment.
*
* @param packageName the package name of the application
- * @param user the user the specified package is running in
+ * @param uid the UID the specified package is running in
* @param message the confirmation message
*
* @return a new instance of this fragment
*
- * @see #show(String, UserHandle, CharSequence, Fragment)
+ * @see #show(String, int, CharSequence, Fragment)
*/
@NonNull
public static DefaultAppConfirmationDialogFragment newInstance(@NonNull String packageName,
- @NonNull UserHandle user, @NonNull CharSequence message) {
+ int uid, @NonNull CharSequence message) {
DefaultAppConfirmationDialogFragment fragment = new DefaultAppConfirmationDialogFragment();
Bundle arguments = new Bundle();
arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
- arguments.putParcelable(Intent.EXTRA_USER, user);
+ arguments.putInt(Intent.EXTRA_UID, uid);
arguments.putCharSequence(Intent.EXTRA_TEXT, message);
fragment.setArguments(arguments);
return fragment;
@@ -64,15 +62,15 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment {
* Show a new instance of this fragment.
*
* @param packageName the package name of the application
- * @param user the user the specified package is running in
+ * @param uid the UID the specified package is running in
* @param message the confirmation message
* @param fragment the parent fragment
*
- * @see #newInstance(String, UserHandle, CharSequence)
+ * @see #newInstance(String, int, CharSequence)
*/
- public static void show(@NonNull String packageName, @NonNull UserHandle user,
+ public static void show(@NonNull String packageName, int uid,
@NonNull CharSequence message, @NonNull Fragment fragment) {
- newInstance(packageName, user, message).show(fragment.getChildFragmentManager(), null);
+ newInstance(packageName, uid, message).show(fragment.getChildFragmentManager(), null);
}
@Override
@@ -81,7 +79,7 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment {
Bundle arguments = getArguments();
mPackageName = arguments.getString(Intent.EXTRA_PACKAGE_NAME);
- mUser = BundleCompat.getParcelable(arguments, Intent.EXTRA_USER, UserHandle.class);
+ mUid = arguments.getInt(Intent.EXTRA_UID);
mMessage = arguments.getCharSequence(Intent.EXTRA_TEXT);
}
@@ -97,7 +95,7 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment {
private void onOk() {
Listener listener = (Listener) getParentFragment();
- listener.setDefaultApp(mPackageName, mUser);
+ listener.setDefaultApp(mPackageName, mUid);
}
/**
@@ -110,6 +108,6 @@ public class DefaultAppConfirmationDialogFragment extends DialogFragment {
*
* @param packageName the package name of the application
*/
- void setDefaultApp(@NonNull String packageName, @NonNull UserHandle user);
+ void setDefaultApp(@NonNull String packageName, int uid);
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
index 2a987167e..fd91d0d3b 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListChildFragment.java
@@ -40,10 +40,12 @@ import androidx.preference.PreferenceScreen;
import com.android.modules.utils.build.SdkLevel;
import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.utils.Utils;
+import com.android.permissioncontroller.role.UserPackage;
import com.android.permissioncontroller.role.utils.PackageUtils;
import com.android.permissioncontroller.role.utils.RoleUiBehaviorUtils;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
+import com.android.settingslib.utils.applications.AppUtils;
import java.util.List;
@@ -241,10 +243,16 @@ public class DefaultAppListChildFragment<PF extends PreferenceFragmentCompat
if (holderApplicationInfos.isEmpty()) {
preference.setIcon(null);
preference.setSummary(R.string.default_app_none);
+ rolePreference.setSummaryContentDescription(null);
} else {
ApplicationInfo holderApplicationInfo = holderApplicationInfos.get(0);
preference.setIcon(Utils.getBadgedIcon(context, holderApplicationInfo));
preference.setSummary(Utils.getAppLabel(holderApplicationInfo, context));
+ UserPackage userPackage = UserPackage.from(holderApplicationInfo);
+ rolePreference.setSummaryContentDescription(
+ AppUtils.getAppContentDescription(context,
+ userPackage.packageName,
+ userPackage.user.getIdentifier()));
}
RoleUiBehaviorUtils.preparePreferenceAsUser(role, holderApplicationInfos,
rolePreference, user, context);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
index 4731c8b0f..89a17004b 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RequestRoleFragment.java
@@ -59,6 +59,7 @@ import com.android.permissioncontroller.role.utils.UiUtils;
import com.android.permissioncontroller.role.utils.UserUtils;
import com.android.role.controller.model.Role;
import com.android.role.controller.model.Roles;
+import com.android.settingslib.utils.applications.AppUtils;
import java.util.ArrayList;
import java.util.List;
@@ -698,6 +699,7 @@ public class RequestRoleFragment extends DialogFragment {
Drawable icon;
String title;
String subtitle;
+ String contentDescription;
if (applicationItem == null) {
applicationInfo = null;
restricted = false;
@@ -706,6 +708,7 @@ public class RequestRoleFragment extends DialogFragment {
title = context.getString(R.string.default_app_none);
subtitle = mHolderUserPackage == null ? context.getString(
R.string.request_role_current_default) : null;
+ contentDescription = null;
} else {
applicationInfo = applicationItem.getApplicationInfo();
UserPackage userPackage = UserPackage.from(applicationInfo);
@@ -717,14 +720,18 @@ public class RequestRoleFragment extends DialogFragment {
subtitle = applicationItem.isHolderApplication()
? context.getString(R.string.request_role_current_default)
: checked ? context.getString(mRole.getRequestDescriptionResource()) : null;
+ contentDescription = AppUtils.getAppContentDescription(context,
+ userPackage.packageName, userPackage.user.getIdentifier());
}
boolean enabled = isEnabled(position);
UiUtils.setViewTreeEnabled(view, enabled && !restricted);
view.setEnabled(enabled);
view.setChecked(checked);
+
holder.iconImage.setImageDrawable(icon);
holder.titleText.setText(title);
+ holder.titleText.setContentDescription(contentDescription);
holder.subtitleText.setVisibility(!TextUtils.isEmpty(subtitle) ? View.VISIBLE
: View.GONE);
holder.subtitleText.setText(subtitle);
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationPreference.java
index 1d3e32c9c..3336aad50 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RoleApplicationPreference.java
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.role.ui;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.TwoStatePreference;
/**
@@ -29,4 +30,9 @@ public interface RoleApplicationPreference extends RestrictionAwarePreference {
*/
@NonNull
TwoStatePreference asTwoStatePreference();
+
+ /**
+ * Sets the preference's content description.
+ */
+ void setContentDescription(@Nullable String contentDescription);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
index bbc123cfe..feafb0ae5 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/RolePreference.java
@@ -17,6 +17,7 @@
package com.android.permissioncontroller.role.ui;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.Preference;
/**
@@ -28,4 +29,9 @@ public interface RolePreference extends TwoTargetPreference, RestrictionAwarePre
*/
@NonNull
Preference asPreference();
+
+ /**
+ * Sets the preference's summary content description.
+ */
+ void setSummaryContentDescription(@Nullable String summaryContentDescription);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
index 764c07497..f0a27284d 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRadioPreference.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
import android.content.Intent;
import android.widget.RadioButton;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -30,10 +31,15 @@ import com.android.permissioncontroller.R;
import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RoleApplicationPreference;
+import java.util.Objects;
+
/** Preference used to represent apps that can be picked as a default app. */
public class AutoRadioPreference extends TwoStatePreference implements
RoleApplicationPreference {
+ @Nullable
+ private String mContentDescription;
+
private final RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
@@ -56,10 +62,21 @@ public class AutoRadioPreference extends TwoStatePreference implements
RadioButton radioButton = (RadioButton) holder.findViewById(R.id.radio_button);
radioButton.setChecked(isChecked());
+ TextView titleText = (TextView) holder.findViewById(android.R.id.title);
+ titleText.setContentDescription(mContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
@Override
+ public void setContentDescription(@Nullable String contentDescription) {
+ if (!Objects.equals(mContentDescription, contentDescription)) {
+ mContentDescription = contentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
index 15fd117d1..28dfc67f9 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoRolePreference.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
+import android.widget.TextView;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
@@ -31,12 +32,17 @@ import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RolePreference;
import com.android.permissioncontroller.role.ui.TwoTargetPreference;
+import java.util.Objects;
+
/**
* Preference for use in auto lists. Extends {@link TwoTargetPreference} in order to make sure of
* shared logic between phone and auto settings UI.
*/
public class AutoRolePreference extends Preference implements RolePreference {
+ @Nullable
+ private String mSummaryContentDescription;
+
private RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
@@ -62,6 +68,14 @@ public class AutoRolePreference extends Preference implements RolePreference {
public void setOnSecondTargetClickListener(@Nullable OnSecondTargetClickListener listener) {}
@Override
+ public void setSummaryContentDescription(@Nullable String summaryContentDescription) {
+ if (!Objects.equals(mSummaryContentDescription, summaryContentDescription)) {
+ mSummaryContentDescription = summaryContentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@@ -70,6 +84,9 @@ public class AutoRolePreference extends Preference implements RolePreference {
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ TextView summaryText = (TextView) holder.findViewById(android.R.id.summary);
+ summaryText.setContentDescription(mSummaryContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
index bfb2b5d1d..e7279278c 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/auto/AutoSwitchPreference.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.auto;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
+import android.widget.TextView;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
@@ -30,12 +31,16 @@ import androidx.preference.SwitchPreference;
import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RoleApplicationPreference;
+import java.util.Objects;
+
/**
* Role application preference represented as a switch.
*/
public class AutoSwitchPreference extends SwitchPreference
implements RoleApplicationPreference {
+ @Nullable
+ private String mContentDescription;
private RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
@@ -58,6 +63,14 @@ public class AutoSwitchPreference extends SwitchPreference
}
@Override
+ public void setContentDescription(@Nullable String contentDescription) {
+ if (!Objects.equals(mContentDescription, contentDescription)) {
+ mContentDescription = contentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@@ -66,6 +79,9 @@ public class AutoSwitchPreference extends SwitchPreference
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ TextView titleText = (TextView) holder.findViewById(android.R.id.title);
+ titleText.setContentDescription(mContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/v35/WalletRoleUiBehavior.java b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/v35/WalletRoleUiBehavior.java
index 09aaa0532..eb1dbb5ef 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/v35/WalletRoleUiBehavior.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/behavior/v35/WalletRoleUiBehavior.java
@@ -42,6 +42,7 @@ import androidx.core.util.Pair;
import androidx.preference.Preference;
import com.android.launcher3.icons.IconFactory;
+import com.android.permissioncontroller.role.ui.RequestRoleItemView;
import com.android.permissioncontroller.role.ui.TwoTargetPreference;
import com.android.permissioncontroller.role.ui.behavior.RoleUiBehavior;
import com.android.role.controller.model.Role;
@@ -73,6 +74,21 @@ public class WalletRoleUiBehavior implements RoleUiBehavior {
}
@Override
+ public void prepareRequestRoleItemViewAsUser(@NonNull Role role,
+ @NonNull RequestRoleItemView itemView, @NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user, @NonNull Context context) {
+ if (isSystemApplication(applicationInfo)) {
+ Pair<Drawable, CharSequence> bannerAndLabel = getLabelAndIconIfItExists(
+ applicationInfo, user, context);
+
+ if (bannerAndLabel != null) {
+ itemView.getIconImageView().setImageDrawable(bannerAndLabel.first);
+ itemView.getTitleTextView().setText(bannerAndLabel.second);
+ }
+ }
+ }
+
+ @Override
public void prepareApplicationPreferenceAsUser(@NonNull Role role,
@NonNull Preference preference, @NonNull ApplicationInfo applicationInfo,
@NonNull UserHandle user, @NonNull Context context) {
@@ -84,21 +100,8 @@ public class WalletRoleUiBehavior implements RoleUiBehavior {
@NonNull ApplicationInfo applicationInfo, boolean setTitle, @NonNull UserHandle user,
@NonNull Context context) {
if (isSystemApplication(applicationInfo)) {
- List<ApduServiceInfo> serviceInfos = getNfcServicesForPackage(
- applicationInfo.packageName, user, context);
-
- Pair<Drawable, CharSequence> bannerAndLabel = null;
- // If the flag is enabled , attempt to fetch it from property
- if (Flags.walletRoleIconPropertyEnabled()) {
- bannerAndLabel =
- getBannerAndLabelFromPackageProperty(context, user,
- applicationInfo.packageName);
- }
- // If it's null, indicating that the property is not set, perform a legacy icon lookup.
- if (bannerAndLabel == null) {
- bannerAndLabel =
- getNonPaymentServiceBannerAndLabelIfExists(serviceInfos, user, context);
- }
+ Pair<Drawable, CharSequence> bannerAndLabel = getLabelAndIconIfItExists(
+ applicationInfo, user, context);
if (bannerAndLabel != null) {
preference.setIcon(bannerAndLabel.first);
if (setTitle) {
@@ -110,6 +113,26 @@ public class WalletRoleUiBehavior implements RoleUiBehavior {
}
}
+ @Nullable
+ private Pair<Drawable, CharSequence> getLabelAndIconIfItExists(
+ @NonNull ApplicationInfo applicationInfo,
+ @NonNull UserHandle user,
+ @NonNull Context context) {
+ Pair<Drawable, CharSequence> result = null;
+ // If the flag is enabled , attempt to fetch it from property
+ if (Flags.walletRoleIconPropertyEnabled()) {
+ result = getBannerAndLabelFromPackageProperty(context, user,
+ applicationInfo.packageName);
+ }
+ if (result != null) {
+ return result;
+ }
+ List<ApduServiceInfo> serviceInfos = getNfcServicesForPackage(
+ applicationInfo.packageName, user, context);
+ // If it's null, indicating that the property is not set, perform a legacy icon lookup.
+ return getNonPaymentServiceBannerAndLabelIfExists(serviceInfos, user, context);
+ }
+
@Nullable
private Pair<Drawable, CharSequence> getBannerAndLabelFromPackageProperty(
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
index 67f04051c..2a943d3d7 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRadioPreference.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.handheld;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
+import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,12 +29,17 @@ import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RoleApplicationPreference;
import com.android.settingslib.widget.SelectorWithWidgetPreference;
+import java.util.Objects;
+
/**
* Preference used to represent apps that can be picked as a default app.
*/
public class HandheldRadioPreference extends SelectorWithWidgetPreference implements
RoleApplicationPreference {
+ @Nullable
+ private String mContentDescription;
+
private final RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
@@ -56,6 +62,14 @@ public class HandheldRadioPreference extends SelectorWithWidgetPreference implem
}
@Override
+ public void setContentDescription(@Nullable String contentDescription) {
+ if (!Objects.equals(mContentDescription, contentDescription)) {
+ mContentDescription = contentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@@ -64,6 +78,9 @@ public class HandheldRadioPreference extends SelectorWithWidgetPreference implem
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ TextView titleText = (TextView) holder.findViewById(android.R.id.title);
+ titleText.setContentDescription(mContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
index 3d09f0b46..46bf3b173 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/handheld/HandheldRolePreference.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import android.view.View;
+import android.widget.TextView;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
@@ -33,6 +34,8 @@ import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RolePreference;
import com.android.settingslib.widget.TwoTargetPreference;
+import java.util.Objects;
+
/**
* {@link Preference} with a settings button.
*
@@ -45,6 +48,9 @@ public class HandheldRolePreference extends TwoTargetPreference implements RoleP
new RestrictionAwarePreferenceMixin(this);
@Nullable
+ private String mSummaryContentDescription;
+
+ @Nullable
private OnSecondTargetClickListener mOnSecondTargetClickListener;
public HandheldRolePreference(@NonNull Context context, @Nullable AttributeSet attrs,
@@ -94,6 +100,14 @@ public class HandheldRolePreference extends TwoTargetPreference implements RoleP
}
@Override
+ public void setSummaryContentDescription(@Nullable String summaryContentDescription) {
+ if (!Objects.equals(mSummaryContentDescription, summaryContentDescription)) {
+ mSummaryContentDescription = summaryContentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@@ -114,6 +128,9 @@ public class HandheldRolePreference extends TwoTargetPreference implements RoleP
// Make the settings button enabled even if the preference itself is disabled.
settingsButton.setEnabled(true);
+ TextView summaryText = (TextView) holder.findViewById(android.R.id.summary);
+ summaryText.setContentDescription(mSummaryContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
index ded6d5cb5..a801c2182 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/specialappaccess/handheld/HandheldSwitchPreference.java
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.specialappaccess.handheld;
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
+import android.widget.TextView;
import androidx.annotation.AttrRes;
import androidx.annotation.NonNull;
@@ -30,10 +31,14 @@ import com.android.permissioncontroller.role.ui.RestrictionAwarePreferenceMixin;
import com.android.permissioncontroller.role.ui.RoleApplicationPreference;
import com.android.settingslib.widget.AppSwitchPreference;
+import java.util.Objects;
+
/** {@link AppSwitchPreference} that is a role application preference. */
public class HandheldSwitchPreference extends AppSwitchPreference
implements RoleApplicationPreference {
+ @Nullable
+ private String mContentDescription;
private RestrictionAwarePreferenceMixin mRestrictionAwarePreferenceMixin =
new RestrictionAwarePreferenceMixin(this);
@@ -56,6 +61,14 @@ public class HandheldSwitchPreference extends AppSwitchPreference
}
@Override
+ public void setContentDescription(@Nullable String contentDescription) {
+ if (!Objects.equals(mContentDescription, contentDescription)) {
+ mContentDescription = contentDescription;
+ notifyChanged();
+ }
+ }
+
+ @Override
public void setRestrictionIntent(@Nullable Intent restrictionIntent) {
mRestrictionAwarePreferenceMixin.setRestrictionIntent(restrictionIntent);
}
@@ -64,6 +77,9 @@ public class HandheldSwitchPreference extends AppSwitchPreference
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ TextView titleText = (TextView) holder.findViewById(android.R.id.title);
+ titleText.setContentDescription(mContentDescription);
+
mRestrictionAwarePreferenceMixin.onAfterBindViewHolder(holder);
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
index 6cd52f576..cb12bf70a 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRoleApplicationPreference.kt
@@ -18,6 +18,7 @@ package com.android.permissioncontroller.role.ui.wear
import android.content.Context
import android.content.Intent
+import androidx.preference.PreferenceViewHolder
import androidx.preference.TwoStatePreference
import com.android.permissioncontroller.role.ui.RoleApplicationPreference
@@ -30,7 +31,8 @@ class WearRoleApplicationPreference(
defaultLabel: String,
val checked: Boolean,
val onDefaultCheckChanged: (Boolean) -> Unit = {},
- private var restrictionIntent: Intent? = null
+ private var restrictionIntent: Intent? = null,
+ private var contentDescription: String? = null,
) : TwoStatePreference(context), RoleApplicationPreference {
init {
title = defaultLabel
@@ -39,10 +41,22 @@ class WearRoleApplicationPreference(
fun getOnCheckChanged(): (Boolean) -> Unit =
restrictionIntent?.let { { _ -> context.startActivity(it) } } ?: onDefaultCheckChanged
+ override fun setContentDescription(contentDescription: String?) {
+ if (this.contentDescription != contentDescription) {
+ this.contentDescription = contentDescription
+ notifyChanged()
+ }
+ }
+
override fun setRestrictionIntent(restrictionIntent: Intent?) {
this.restrictionIntent = restrictionIntent
isEnabled = restrictionIntent == null
}
override fun asTwoStatePreference(): TwoStatePreference = this
+
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+ holder.findViewById(android.R.id.title)?.let { it.contentDescription = contentDescription }
+ }
}
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
index 43acf4293..670c136ea 100644
--- a/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
+++ b/PermissionController/src/com/android/permissioncontroller/role/ui/wear/WearRolePreference.kt
@@ -19,6 +19,7 @@ package com.android.permissioncontroller.role.ui.wear
import android.content.Context
import android.content.Intent
import androidx.preference.Preference
+import androidx.preference.PreferenceViewHolder
import com.android.permissioncontroller.role.ui.RolePreference
import com.android.permissioncontroller.role.ui.TwoTargetPreference.OnSecondTargetClickListener
import com.android.settingslib.widget.TwoTargetPreference
@@ -28,13 +29,21 @@ class WearRolePreference(
context: Context,
val label: String,
val onDefaultClicked: () -> Unit = {},
- private var restrictionIntent: Intent? = null
+ private var restrictionIntent: Intent? = null,
+ private var summaryContentDescription: String? = null,
) : TwoTargetPreference(context), RolePreference {
override fun setOnSecondTargetClickListener(listener: OnSecondTargetClickListener?) {
// no-op
}
+ override fun setSummaryContentDescription(summaryContentDescription: String?) {
+ if (this.summaryContentDescription != summaryContentDescription) {
+ this.summaryContentDescription = summaryContentDescription
+ notifyChanged()
+ }
+ }
+
override fun setRestrictionIntent(restrictionIntent: Intent?) {
this.restrictionIntent = restrictionIntent
setEnabled(restrictionIntent == null)
@@ -42,6 +51,14 @@ class WearRolePreference(
override fun asPreference(): Preference = this
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+
+ holder.findViewById(android.R.id.summary)?.let {
+ it.contentDescription = summaryContentDescription
+ }
+ }
+
fun getOnClicked(): () -> Unit =
restrictionIntent?.let { { context.startActivity(it) } } ?: onDefaultClicked
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
index b5a66da06..d29b0aa3e 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/SafetyCenterFragment.kt
@@ -61,7 +61,6 @@ abstract class SafetyCenterFragment : SettingsBasePreferenceFragment() {
} else {
super.onCreateAdapter(preferenceScreen)
}
-
/* By default, the PreferenceGroupAdapter does setHasStableIds(true). Since each Preference
* is internally allocated with an auto-incremented ID, it does not allow us to gracefully
* update only changed preferences based on SafetyPreferenceComparisonCallback. In order to
@@ -77,10 +76,15 @@ abstract class SafetyCenterFragment : SettingsBasePreferenceFragment() {
.split(",")
safetyCenterSessionId = requireArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)
+ val activity = requireActivity()
safetyCenterViewModel =
ViewModelProvider(
- requireActivity(),
- LiveSafetyCenterViewModelFactory(requireActivity().getApplication()),
+ activity,
+ LiveSafetyCenterViewModelFactory(
+ activity.application,
+ activity.taskId,
+ sameTaskSourceIds,
+ ),
)
.get(SafetyCenterViewModel::class.java)
safetyCenterViewModel.safetyCenterUiLiveData.observe(this) { uiData: SafetyCenterUiData? ->
@@ -91,8 +95,7 @@ abstract class SafetyCenterFragment : SettingsBasePreferenceFragment() {
displayErrorDetails(errorDetails)
}
- val safetyCenterIntent: ParsedSafetyCenterIntent =
- requireActivity().intent.toSafetyCenterIntent()
+ val safetyCenterIntent: ParsedSafetyCenterIntent = activity.intent.toSafetyCenterIntent()
val isQsFragment =
getArguments()?.getBoolean(QUICK_SETTINGS_SAFETY_CENTER_FRAGMENT, false) ?: false
collapsableIssuesCardHelper =
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/IssueUiData.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/IssueUiData.kt
new file mode 100644
index 000000000..e260bb917
--- /dev/null
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/IssueUiData.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.permissioncontroller.safetycenter.ui.model
+
+import android.safetycenter.SafetyCenterIssue
+
+/** UI model representation of [SafetyCenterIssue] */
+data class IssueUiData(
+ val issue: SafetyCenterIssue,
+ val isDismissed: Boolean,
+ val resolvedIssueActionId: String? = null,
+ val launchTaskId: Int? = null,
+)
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt
index 4ddcf1c3d..0b976f49d 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/LiveSafetyCenterViewModel.kt
@@ -43,11 +43,16 @@ import com.android.safetycenter.internaldata.SafetyCenterIds
/* A SafetyCenterViewModel that talks to the real backing service for Safety Center. */
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
+class LiveSafetyCenterViewModel(
+ app: Application,
+ private val taskId: Int,
+ private val sameTaskSourceIds: List<String>,
+) : SafetyCenterViewModel(app) {
private val TAG: String = LiveSafetyCenterViewModel::class.java.simpleName
override val statusUiLiveData: LiveData<StatusUiData>
get() = safetyCenterUiLiveData.map { StatusUiData(it.safetyCenterData) }
+
override val safetyCenterUiLiveData: LiveData<SafetyCenterUiData> by this::_safetyCenterLiveData
override val errorLiveData: LiveData<SafetyCenterErrorDetails> by this::_errorLiveData
@@ -65,7 +70,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
private val safetyCenterManager = app.getSystemService(SafetyCenterManager::class.java)!!
override fun getCurrentSafetyCenterDataAsUiData(): SafetyCenterUiData =
- SafetyCenterUiData(safetyCenterManager.safetyCenterData)
+ uiData(safetyCenterManager.safetyCenterData)
override fun dismissIssue(issue: SafetyCenterIssue) {
safetyCenterManager.dismissSafetyCenterIssue(issue.id)
@@ -74,7 +79,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
override fun executeIssueAction(
issue: SafetyCenterIssue,
action: SafetyCenterIssue.Action,
- launchTaskId: Int?
+ launchTaskId: Int?,
) {
val issueId =
if (launchTaskId != null) {
@@ -107,9 +112,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
override fun navigateToSafetyCenter(context: Context, navigationSource: NavigationSource?) {
val intent = Intent(ACTION_SAFETY_CENTER)
- if (navigationSource != null) {
- navigationSource.addToIntent(intent)
- }
+ navigationSource?.addToIntent(intent)
context.startActivity(intent)
}
@@ -132,7 +135,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
} else {
safetyCenterManager.refreshSafetySources(
SafetyCenterManager.REFRESH_REASON_PAGE_OPEN,
- safetySourceIds
+ safetySourceIds,
)
}
}
@@ -174,7 +177,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
override fun onActive() {
safetyCenterManager.addOnSafetyCenterDataChangedListener(
getMainExecutor(app.applicationContext),
- this
+ this,
)
super.onActive()
}
@@ -209,7 +212,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
Log.d(
TAG,
"Received SafetyCenterData while issue resolution animations" +
- " occurring. Will update UI with new data soon."
+ " occurring. Will update UI with new data soon.",
)
return
}
@@ -254,7 +257,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
private fun isCurrentlyScanning(): Boolean = value?.safetyCenterData?.isScanning() ?: false
private fun sendNextData() {
- value = SafetyCenterUiData(safetyCenterDataQueue.removeFirst())
+ value = uiData(safetyCenterDataQueue.removeFirst())
}
private fun skipNextData() = safetyCenterDataQueue.removeFirst()
@@ -270,7 +273,7 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
// The current SafetyCenterData still contains the resolved SafetyCenterIssue objects.
// Send it with the resolved IDs so the UI can generate the correct preferences and
// trigger the right animations for issue resolution.
- value = SafetyCenterUiData(currentData, currentResolvedIssues)
+ value = uiData(currentData, currentResolvedIssues)
}
@MainThread
@@ -279,6 +282,11 @@ class LiveSafetyCenterViewModel(app: Application) : SafetyCenterViewModel(app) {
maybeProcessDataToNextResolvedIssues()
}
}
+
+ private fun uiData(
+ safetyCenterData: SafetyCenterData,
+ resolvedIssues: Map<IssueId, ActionId> = emptyMap(),
+ ) = SafetyCenterUiData(safetyCenterData, taskId, sameTaskSourceIds, resolvedIssues)
}
/** Returns inflight issues pending resolution */
@@ -309,8 +317,15 @@ private val SafetyCenterData.allResolvableIssues: Sequence<SafetyCenterIssue>
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
-class LiveSafetyCenterViewModelFactory(private val app: Application) : ViewModelProvider.Factory {
+class LiveSafetyCenterViewModelFactory
+@JvmOverloads
+constructor(
+ private val app: Application,
+ private val taskId: Int = 0,
+ private val sameTaskSourceIds: List<String> = emptyList(),
+) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
- @Suppress("UNCHECKED_CAST") return LiveSafetyCenterViewModel(app) as T
+ @Suppress("UNCHECKED_CAST")
+ return LiveSafetyCenterViewModel(app, taskId, sameTaskSourceIds) as T
}
}
diff --git a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
index 69a315f08..d8aadae2f 100644
--- a/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/safetycenter/ui/model/SafetyCenterUiData.kt
@@ -29,11 +29,21 @@ import com.android.safetycenter.internaldata.SafetyCenterIds
import com.android.safetycenter.internaldata.SafetyCenterIssueKey
/** UI model representation of Safety Center Data */
+@RequiresApi(TIRAMISU)
data class SafetyCenterUiData(
val safetyCenterData: SafetyCenterData,
- val resolvedIssues: Map<IssueId, ActionId> = emptyMap()
+ private val taskId: Int,
+ private val sameTaskSourceIds: List<String>,
+ val resolvedIssues: Map<IssueId, ActionId> = emptyMap(),
) {
- @RequiresApi(TIRAMISU)
+
+ val issueUiDatas: List<IssueUiData> by
+ lazy(LazyThreadSafetyMode.NONE) {
+ safetyCenterData.issues.map {
+ IssueUiData(it, false, resolvedIssues[it.id], getLaunchTaskIdForIssue(it))
+ }
+ }
+
fun getMatchingIssue(issueKey: SafetyCenterIssueKey): SafetyCenterIssue? {
return safetyCenterData.issues.find {
SafetyCenterIds.issueIdFromString(it.id).safetyCenterIssueKey == issueKey
@@ -67,7 +77,7 @@ data class SafetyCenterUiData(
@RequiresApi(UPSIDE_DOWN_CAKE)
private fun selectMatchingIssuesForGroup(
groupId: String,
- issues: List<SafetyCenterIssue>
+ issues: List<SafetyCenterIssue>,
): List<SafetyCenterIssue> {
val issuesToGroups = safetyCenterData.extras.getBundle(ISSUES_TO_GROUPS_BUNDLE_KEY)
return issues.filter {
@@ -84,4 +94,12 @@ data class SafetyCenterUiData(
@RequiresApi(UPSIDE_DOWN_CAKE)
fun SafetyCenterData.visibleDismissedIssues() =
dismissedIssues.filter { it.severityLevel > ISSUE_SEVERITY_LEVEL_OK }
+
+ private fun getLaunchTaskIdForIssue(issue: SafetyCenterIssue): Int? {
+ val sourceId: String =
+ SafetyCenterIds.issueIdFromString(issue.id)
+ .getSafetyCenterIssueKey()
+ .getSafetySourceId()
+ return if (sameTaskSourceIds.contains(sourceId)) taskId else null
+ }
}
diff --git a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
index ca0392716..e53fabc90 100644
--- a/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
+++ b/PermissionController/tests/mocking/src/com/android/permissioncontroller/tests/mocking/safetycenter/ui/model/SafetyCenterUiDataTest.kt
@@ -18,6 +18,7 @@ package com.android.permissioncontroller.tests.mocking.safetycenter.ui.model
import android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE
import android.os.Bundle
+import android.os.UserHandle
import android.safetycenter.SafetyCenterData
import android.safetycenter.SafetyCenterEntryGroup
import android.safetycenter.SafetyCenterEntryOrGroup
@@ -28,8 +29,14 @@ import android.safetycenter.SafetyCenterIssue.ISSUE_SEVERITY_LEVEL_RECOMMENDATIO
import android.safetycenter.SafetyCenterStatus
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
+import com.android.permissioncontroller.safetycenter.ui.model.ActionId
+import com.android.permissioncontroller.safetycenter.ui.model.IssueId
+import com.android.permissioncontroller.safetycenter.ui.model.IssueUiData
import com.android.permissioncontroller.safetycenter.ui.model.SafetyCenterUiData
import com.android.safetycenter.internaldata.SafetyCenterBundles.ISSUES_TO_GROUPS_BUNDLE_KEY
+import com.android.safetycenter.internaldata.SafetyCenterIds
+import com.android.safetycenter.internaldata.SafetyCenterIssueId
+import com.android.safetycenter.internaldata.SafetyCenterIssueKey
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
@@ -40,42 +47,42 @@ class SafetyCenterUiDataTest {
@Test
fun getMatchingGroup_validMatchingGroup_returnsExpectedEntryGroup() {
- val matchingGroup = createSafetyCenterEntryGroup(MATCHING_GROUP_ID)
- val nonMatchingGroup = createSafetyCenterEntryGroup(NON_MATCHING_GROUP_ID)
+ val matchingGroup = entryGroup(MATCHING_GROUP_ID)
+ val nonMatchingGroup = entryGroup(NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(entryGroups = listOf(matchingGroup, nonMatchingGroup))
- val result = SafetyCenterUiData(safetyCenterData).getMatchingGroup(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingGroup(MATCHING_GROUP_ID)
assertThat(result).isEqualTo(matchingGroup)
}
@Test
fun getMatchingGroup_noMatchingGroup_returnsNull() {
- val nonMatchingGroup = createSafetyCenterEntryGroup(NON_MATCHING_GROUP_ID)
+ val nonMatchingGroup = entryGroup(NON_MATCHING_GROUP_ID)
val safetyCenterData = createSafetyCenterData(entryGroups = listOf(nonMatchingGroup))
- val result = SafetyCenterUiData(safetyCenterData).getMatchingGroup(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingGroup(MATCHING_GROUP_ID)
assertThat(result).isNull()
}
@Test
fun getMatchingIssues_defaultMatchingIssue_noExtras_returnsListOfIssues() {
- val defaultMatchingIssue = createSafetyCenterIssue("id1", MATCHING_GROUP_ID)
- val nonMatchingIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val defaultMatchingIssue = issue("id1", MATCHING_GROUP_ID)
+ val nonMatchingIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(issues = listOf(defaultMatchingIssue, nonMatchingIssue))
- val result = SafetyCenterUiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(defaultMatchingIssue)
}
@Test
fun getMatchingIssues_defaultMatchingIssue_unrelatedExtras_returnsListOfIssues() {
- val defaultMatchingIssue = createSafetyCenterIssue("id1", MATCHING_GROUP_ID)
- val nonMatchingIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val defaultMatchingIssue = issue("id1", MATCHING_GROUP_ID)
+ val nonMatchingIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
issues = listOf(defaultMatchingIssue, nonMatchingIssue),
@@ -84,21 +91,21 @@ class SafetyCenterUiDataTest {
Bundle().apply {
putStringArrayList(
nonMatchingIssue.id,
- arrayListOf(NON_MATCHING_GROUP_ID)
+ arrayListOf(NON_MATCHING_GROUP_ID),
)
}
- )
+ ),
)
- val result = SafetyCenterUiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(defaultMatchingIssue)
}
@Test
fun getMatchingIssues_mappingMatchingIssue_returnsListOfIssues() {
- val mappingMatchingIssue = createSafetyCenterIssue("id1", NON_MATCHING_GROUP_ID)
- val nonMatchingIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val mappingMatchingIssue = issue("id1", NON_MATCHING_GROUP_ID)
+ val nonMatchingIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
issues = listOf(mappingMatchingIssue, nonMatchingIssue),
@@ -107,51 +114,50 @@ class SafetyCenterUiDataTest {
Bundle().apply {
putStringArrayList(
mappingMatchingIssue.id,
- arrayListOf(MATCHING_GROUP_ID)
+ arrayListOf(MATCHING_GROUP_ID),
)
}
- )
+ ),
)
- val result = SafetyCenterUiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(mappingMatchingIssue)
}
@Test
fun getMatchingIssues_noDefaultMatchingIssue_returnsEmptyList() {
- val nonMatchingIssue = createSafetyCenterIssue("id1", NON_MATCHING_GROUP_ID)
- val dismissedIssue = createSafetyCenterIssue("id2", MATCHING_GROUP_ID)
+ val nonMatchingIssue = issue("id1", NON_MATCHING_GROUP_ID)
+ val dismissedIssue = issue("id2", MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
issues = listOf(nonMatchingIssue),
- dismissedIssues = listOf(dismissedIssue)
+ dismissedIssues = listOf(dismissedIssue),
)
- val result = SafetyCenterUiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingIssues(MATCHING_GROUP_ID)
assertThat(result).isEmpty()
}
@Test
fun getMatchingDismissedIssues_defaultMatchingDismissedIssue_returnsListOfDismissedIssues() {
- val defaultMatchingDismissedIssue = createSafetyCenterIssue("id1", MATCHING_GROUP_ID)
- val nonMatchingDismissedIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val defaultMatchingDismissedIssue = issue("id1", MATCHING_GROUP_ID)
+ val nonMatchingDismissedIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
dismissedIssues = listOf(defaultMatchingDismissedIssue, nonMatchingDismissedIssue)
)
- val result =
- SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(defaultMatchingDismissedIssue)
}
@Test
fun getMatchingDismissedIssues_defaultMatchingDismissedIssue2_returnsListOfDismissedIssues() {
- val defaultMatchingDismissedIssue = createSafetyCenterIssue("id1", MATCHING_GROUP_ID)
- val nonMatchingDismissedIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val defaultMatchingDismissedIssue = issue("id1", MATCHING_GROUP_ID)
+ val nonMatchingDismissedIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
dismissedIssues = listOf(defaultMatchingDismissedIssue, nonMatchingDismissedIssue),
@@ -160,22 +166,21 @@ class SafetyCenterUiDataTest {
Bundle().apply {
putStringArrayList(
nonMatchingDismissedIssue.id,
- arrayListOf(NON_MATCHING_GROUP_ID)
+ arrayListOf(NON_MATCHING_GROUP_ID),
)
}
- )
+ ),
)
- val result =
- SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(defaultMatchingDismissedIssue)
}
@Test
fun getMatchingDismissedIssues_mappingMatchingDismissedIssue_returnsListOfDismissedIssues() {
- val mappingMatchingDismissedIssue = createSafetyCenterIssue("id1", NON_MATCHING_GROUP_ID)
- val nonMatchingDismissedIssue = createSafetyCenterIssue("id2", NON_MATCHING_GROUP_ID)
+ val mappingMatchingDismissedIssue = issue("id1", NON_MATCHING_GROUP_ID)
+ val nonMatchingDismissedIssue = issue("id2", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
dismissedIssues = listOf(mappingMatchingDismissedIssue, nonMatchingDismissedIssue),
@@ -184,30 +189,28 @@ class SafetyCenterUiDataTest {
Bundle().apply {
putStringArrayList(
mappingMatchingDismissedIssue.id,
- arrayListOf(MATCHING_GROUP_ID)
+ arrayListOf(MATCHING_GROUP_ID),
)
}
- )
+ ),
)
- val result =
- SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(mappingMatchingDismissedIssue)
}
@Test
fun getMatchingDismissedIssues_noDefaultMatchingDismissedIssue_returnsEmptyList() {
- val nonMatchingDismissedIssue = createSafetyCenterIssue("id1", NON_MATCHING_GROUP_ID)
- val nonDismissedIssue = createSafetyCenterIssue("id2", MATCHING_GROUP_ID)
+ val nonMatchingDismissedIssue = issue("id1", NON_MATCHING_GROUP_ID)
+ val nonDismissedIssue = issue("id2", MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
issues = listOf(nonDismissedIssue),
- dismissedIssues = listOf(nonMatchingDismissedIssue)
+ dismissedIssues = listOf(nonMatchingDismissedIssue),
)
- val result =
- SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
assertThat(result).isEmpty()
}
@@ -215,24 +218,12 @@ class SafetyCenterUiDataTest {
@Test
fun getMatchingDismissedIssues_doesntReturnGreenIssues() {
val greenDismissedIssue =
- createSafetyCenterIssue(
- "id1",
- MATCHING_GROUP_ID,
- severityLevel = ISSUE_SEVERITY_LEVEL_OK
- )
+ issue("id1", MATCHING_GROUP_ID, severityLevel = ISSUE_SEVERITY_LEVEL_OK)
val yellowDismissedIssue =
- createSafetyCenterIssue(
- "id2",
- MATCHING_GROUP_ID,
- severityLevel = ISSUE_SEVERITY_LEVEL_RECOMMENDATION
- )
+ issue("id2", MATCHING_GROUP_ID, severityLevel = ISSUE_SEVERITY_LEVEL_RECOMMENDATION)
val redDismissedIssue =
- createSafetyCenterIssue(
- "id3",
- MATCHING_GROUP_ID,
- severityLevel = ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING
- )
- val nonMatchingDismissedIssue = createSafetyCenterIssue("id4", NON_MATCHING_GROUP_ID)
+ issue("id3", MATCHING_GROUP_ID, severityLevel = ISSUE_SEVERITY_LEVEL_CRITICAL_WARNING)
+ val nonMatchingDismissedIssue = issue("id4", NON_MATCHING_GROUP_ID)
val safetyCenterData =
createSafetyCenterData(
dismissedIssues =
@@ -240,25 +231,82 @@ class SafetyCenterUiDataTest {
redDismissedIssue,
yellowDismissedIssue,
greenDismissedIssue,
- nonMatchingDismissedIssue
- ),
+ nonMatchingDismissedIssue,
+ )
)
- val result =
- SafetyCenterUiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
+ val result = uiData(safetyCenterData).getMatchingDismissedIssues(MATCHING_GROUP_ID)
assertThat(result).containsExactly(redDismissedIssue, yellowDismissedIssue).inOrder()
}
+ @Test
+ fun issueUiDatas_returnsIssueUiData() {
+ val issue1 = issue("id1", "group1")
+ val issue2 = issue("id2", "group2")
+ val safetyCenterData = createSafetyCenterData(listOf(issue1, issue2))
+
+ val result = uiData(safetyCenterData).issueUiDatas
+
+ assertThat(result)
+ .containsExactly(
+ IssueUiData(issue1, isDismissed = false),
+ IssueUiData(issue2, isDismissed = false),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun issueUiDatas_withResolvedIssues_returnsExpectedIssueUiData() {
+ val resolvedActionId = "actionId"
+ val resolvedIssue = issue("resolvedId", "group1")
+ val unresolvedIssue = issue("unresolvedId", "group2")
+ val safetyCenterData = createSafetyCenterData(listOf(resolvedIssue, unresolvedIssue))
+
+ val result =
+ uiData(safetyCenterData, resolvedIssues = mapOf(resolvedIssue.id to resolvedActionId))
+ .issueUiDatas
+
+ assertThat(result[0].resolvedIssueActionId).isEqualTo(resolvedActionId)
+ assertThat(result[1].resolvedIssueActionId).isNull()
+ }
+
+ @Test
+ fun issueUiDatas_withSameTaskSourceId_returnsExpectedIssueUiData() {
+ val taskId = 42
+ val sameTaskSourceId = "sameTaskSourceId"
+ val sameTaskIssue =
+ issueWithEncodedId(
+ encodeIssueId("sameTaskIssue", sourceId = sameTaskSourceId),
+ "group1",
+ )
+ val differentTaskIssue = issue("differentTaskIssue", "group2")
+ val safetyCenterData = createSafetyCenterData(listOf(sameTaskIssue, differentTaskIssue))
+
+ val result =
+ uiData(safetyCenterData, taskId, sameTaskSourceIds = listOf(sameTaskSourceId))
+ .issueUiDatas
+
+ assertThat(result[0].launchTaskId).isEqualTo(taskId)
+ assertThat(result[1].launchTaskId).isNull()
+ }
+
private companion object {
const val MATCHING_GROUP_ID = "matching_group_id"
const val NON_MATCHING_GROUP_ID = "non_matching_group_id"
+ private fun uiData(
+ safetyCenterData: SafetyCenterData,
+ taskId: Int = 0,
+ sameTaskSourceIds: List<String> = emptyList(),
+ resolvedIssues: Map<IssueId, ActionId> = emptyMap(),
+ ) = SafetyCenterUiData(safetyCenterData, taskId, sameTaskSourceIds, resolvedIssues)
+
fun createSafetyCenterData(
issues: List<SafetyCenterIssue> = listOf(),
entryGroups: List<SafetyCenterEntryGroup> = listOf(),
dismissedIssues: List<SafetyCenterIssue> = listOf(),
- extras: Bundle = Bundle()
+ extras: Bundle = Bundle(),
): SafetyCenterData {
val safetyCenterStatus =
SafetyCenterStatus.Builder("status title", "status summary").build()
@@ -276,20 +324,44 @@ class SafetyCenterUiDataTest {
return builder.build()
}
- fun createSafetyCenterEntryGroup(groupId: String) =
+ fun createSafetyCenterExtras(issuesToGroupsMapping: Bundle) =
+ Bundle().apply { putBundle(ISSUES_TO_GROUPS_BUNDLE_KEY, issuesToGroupsMapping) }
+
+ fun entryGroup(groupId: String) =
SafetyCenterEntryGroup.Builder(groupId, "group title").build()
- fun createSafetyCenterIssue(
+ fun issue(
issueId: String,
groupId: String,
- severityLevel: Int = ISSUE_SEVERITY_LEVEL_RECOMMENDATION
+ severityLevel: Int = ISSUE_SEVERITY_LEVEL_RECOMMENDATION,
+ ): SafetyCenterIssue = issueWithEncodedId(encodeIssueId(issueId), groupId, severityLevel)
+
+ private fun issueWithEncodedId(
+ encodedIssueId: String,
+ groupId: String,
+ severityLevel: Int = ISSUE_SEVERITY_LEVEL_RECOMMENDATION,
) =
- SafetyCenterIssue.Builder(issueId, "issue title", "issue summary")
+ SafetyCenterIssue.Builder(encodedIssueId, "issue title", "issue summary")
.setSeverityLevel(severityLevel)
.setGroupId(groupId)
.build()
- fun createSafetyCenterExtras(issuesToGroupsMapping: Bundle) =
- Bundle().apply { putBundle(ISSUES_TO_GROUPS_BUNDLE_KEY, issuesToGroupsMapping) }
+ fun encodeIssueId(
+ sourceIssueId: String,
+ sourceId: String = "defaultSource",
+ issueTypeId: String = "defaultIssueTypeId",
+ ): String =
+ SafetyCenterIds.encodeToString(
+ SafetyCenterIssueId.newBuilder()
+ .setSafetyCenterIssueKey(
+ SafetyCenterIssueKey.newBuilder()
+ .setSafetySourceId(sourceId)
+ .setSafetySourceIssueId(sourceIssueId)
+ .setUserId(UserHandle.myUserId())
+ .build()
+ )
+ .setIssueTypeId(issueTypeId)
+ .build()
+ )
}
}
diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt
index f0dab21ec..23074a06f 100644
--- a/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt
+++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/Chip.kt
@@ -33,7 +33,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.Hyphens
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
@@ -194,11 +193,7 @@ fun Chip(
textAlign = if (hasSecondaryLabel || hasIcon) TextAlign.Start else TextAlign.Center,
overflow = TextOverflow.Ellipsis,
maxLines = labelMaxLines ?: if (hasSecondaryLabel) 1 else 2,
- style =
- MaterialTheme.typography.button.copy(
- fontWeight = FontWeight.W600,
- hyphens = Hyphens.Auto,
- ),
+ style = MaterialTheme.typography.button.copy(hyphens = Hyphens.Auto),
)
}
diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt
index 7dc26179d..6ed81353a 100644
--- a/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt
+++ b/PermissionController/wear-permission-components/src/wear.permission.components/material2/ListHeader.kt
@@ -34,7 +34,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.Hyphens
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.LocalContentColor
@@ -72,11 +71,7 @@ fun ListHeader(
) {
CompositionLocalProvider(
LocalContentColor provides contentColor,
- LocalTextStyle provides
- MaterialTheme.typography.title3.copy(
- fontWeight = FontWeight.W600,
- hyphens = Hyphens.Auto,
- ),
+ LocalTextStyle provides MaterialTheme.typography.title3.copy(hyphens = Hyphens.Auto),
) {
content()
}
diff --git a/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt
index 1a7524e7c..5f1c8dd2c 100644
--- a/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt
+++ b/PermissionController/wear-permission-components/src/wear.permission.components/material3/WearPermissionButton.kt
@@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.requiredSizeIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.Hyphens
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -112,11 +111,7 @@ internal fun WearPermissionButtonInternal(
text = label,
modifier = Modifier.fillMaxWidth(),
maxLines = labelMaxLines ?: LocalTextConfiguration.current.maxLines,
- style =
- LocalTextStyle.current.copy(
- fontWeight = FontWeight.W600,
- hyphens = Hyphens.Auto,
- ),
+ style = LocalTextStyle.current.copy(hyphens = Hyphens.Auto),
)
}
}
diff --git a/SafetyCenter/OWNERS b/SafetyCenter/OWNERS
index d9039e915..229331d3c 100644
--- a/SafetyCenter/OWNERS
+++ b/SafetyCenter/OWNERS
@@ -4,7 +4,6 @@ simonjw@google.com
davidcoffin@google.com
elliotsisteron@google.com
fiscella@google.com
-shrigupt@google.com
jtomljanovic@google.com
deweytyl@google.com
maxspencer@google.com
diff --git a/SafetyCenter/Resources/res/values-mk-v35/strings.xml b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
index c4fc4bd17..1201ae74f 100644
--- a/SafetyCenter/Resources/res/values-mk-v35/strings.xml
+++ b/SafetyCenter/Resources/res/values-mk-v35/strings.xml
@@ -21,7 +21,7 @@
<string name="cellular_network_security_summary" msgid="7319307247487475572">"Тип мрежа, шифрирање, контроли за известувања"</string>
<string name="biometrics_title_for_private_profile" msgid="542819107383037820"></string>
<string name="privacy_title" msgid="7047524783080782769">"Приватност"</string>
- <string name="privacy_sources_title" msgid="309304028326660956">"Контроли на приватноста"</string>
+ <string name="privacy_sources_title" msgid="309304028326660956">"Контроли за приватност"</string>
<string name="privacy_sources_summary" msgid="2165270848857537278">"Дозволи, контроли"</string>
<string name="privacy_additional_title" msgid="4239060639056083649"></string>
<string name="private_space_title" msgid="6158245041481535879">"Приватен простор"</string>
diff --git a/SafetyCenter/Resources/res/values-mk/strings.xml b/SafetyCenter/Resources/res/values-mk/strings.xml
index 2b2414d0d..379a5234b 100644
--- a/SafetyCenter/Resources/res/values-mk/strings.xml
+++ b/SafetyCenter/Resources/res/values-mk/strings.xml
@@ -33,9 +33,9 @@
<string name="permission_manager_title" msgid="5277347862821255015">"Управувач со дозволи"</string>
<string name="permission_manager_summary" msgid="8099852107340970790">"Го контролира пристапот на апликациите до вашите податоци"</string>
<string name="permission_manager_search_terms" msgid="2895147613099694722">"Дозволи, Управувач со дозволи"</string>
- <string name="privacy_controls_title" msgid="5322875777945432395">"Контроли за приватноста"</string>
+ <string name="privacy_controls_title" msgid="5322875777945432395">"Контроли за приватност"</string>
<string name="privacy_controls_summary" msgid="2402066941190435424">"Го контролира пристапот на уредот до микрофонот, камерата и друго"</string>
- <string name="privacy_controls_search_terms" msgid="3774472175934304165">"Приватност, Контроли на приватноста"</string>
+ <string name="privacy_controls_search_terms" msgid="3774472175934304165">"Приватност, Контроли за приватност"</string>
<string name="advanced_title" msgid="8745436380690561172">"Повеќе поставки"</string>
<string name="advanced_security_title" msgid="1126833338772188155">"Повеќе поставки за безбедност"</string>
<string name="advanced_security_summary" msgid="6172253327022425123">"Шифрирање, акредитиви и друго"</string>
diff --git a/service/java/com/android/permission/util/UserUtils.java b/service/java/com/android/permission/util/UserUtils.java
index 82e9cbbae..ae8e794b6 100644
--- a/service/java/com/android/permission/util/UserUtils.java
+++ b/service/java/com/android/permission/util/UserUtils.java
@@ -70,8 +70,7 @@ public final class UserUtils {
return;
}
- Context userContext = UserUtils.getUserContext(userId, context);
- List<UserHandle> profiles = getUserProfiles(userContext, true);
+ List<UserHandle> profiles = getUserProfiles(userId, context, true);
final int profilesSize = profiles.size();
for (int i = 0; i < profilesSize; i++) {
int profileId = profiles.get(i).getIdentifier();
@@ -112,26 +111,29 @@ public final class UserUtils {
}
}
- /** Returns all the enabled user profiles on the device. */
+ /** Returns all the enabled user profiles on the device for a specified user. */
@NonNull
- public static List<UserHandle> getUserProfiles(@NonNull Context context) {
- return getUserProfiles(context, false);
+ public static List<UserHandle> getUserProfiles(@UserIdInt int userId,
+ @NonNull Context context) {
+ return getUserProfiles(userId, context, false);
}
/**
- * Returns all the enabled user profiles on the device
+ * Returns all the enabled user profiles on the device for a specified user
*
+ * @param userId the user id to check
* @param context the {@link Context}
* @param excludePrivate {@code true} to exclude private profiles from returned list of users
*/
@NonNull
- public static List<UserHandle> getUserProfiles(@NonNull Context context,
+ public static List<UserHandle> getUserProfiles(@UserIdInt int userId, @NonNull Context context,
boolean excludePrivate) {
- UserManager userManager = context.getSystemService(UserManager.class);
// This call requires the QUERY_USERS permission.
final long identity = Binder.clearCallingIdentity();
try {
- List<UserHandle> profiles = userManager.getUserProfiles();
+ Context userContext = getUserContext(userId, context);
+ UserManager userUserManager = userContext.getSystemService(UserManager.class);
+ List<UserHandle> profiles = userUserManager.getUserProfiles();
if (!excludePrivate) {
return profiles;
}
@@ -139,7 +141,7 @@ public final class UserUtils {
final int profilesSize = profiles.size();
for (int i = 0; i < profilesSize; i++) {
UserHandle user = profiles.get(i);
- if (!isPrivateProfile(user.getIdentifier(), context)) {
+ if (!isPrivateProfile(user.getIdentifier(), userContext)) {
filteredProfiles.add(user);
}
}
@@ -164,11 +166,11 @@ public final class UserUtils {
@Nullable
private static UserHandle getProfileParent(@UserIdInt int userId, @NonNull Context context) {
Context userContext = getUserContext(userId, context);
- UserManager userManager = userContext.getSystemService(UserManager.class);
+ UserManager userUserManager = userContext.getSystemService(UserManager.class);
// This call requires the INTERACT_ACROSS_USERS permission.
final long identity = Binder.clearCallingIdentity();
try {
- return userManager.getProfileParent(UserHandle.of(userId));
+ return userUserManager.getProfileParent(UserHandle.of(userId));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -201,8 +203,8 @@ public final class UserUtils {
final long identity = Binder.clearCallingIdentity();
try {
Context userContext = getUserContext(userId, context);
- UserManager userManager = userContext.getSystemService(UserManager.class);
- return userManager != null && userManager.isPrivateProfile();
+ UserManager userUserManager = userContext.getSystemService(UserManager.class);
+ return userUserManager != null && userUserManager.isPrivateProfile();
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index 5bc79efbb..e5d20ef9d 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -564,8 +564,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback
+ " for role");
return;
}
- Context userContext = UserUtils.getUserContext(userId, getContext());
- List<UserHandle> profiles = UserUtils.getUserProfiles(userContext, true);
+ List<UserHandle> profiles = UserUtils.getUserProfiles(userId, getContext(), true);
if (!profiles.contains(UserHandle.of(activeUserId))) {
Log.e(LOG_TAG, "User " + activeUserId + " is not in the same profile-group as "
+ userId);
diff --git a/service/java/com/android/safetycenter/UserProfileGroup.java b/service/java/com/android/safetycenter/UserProfileGroup.java
index 1f5258437..44cb8d3d6 100644
--- a/service/java/com/android/safetycenter/UserProfileGroup.java
+++ b/service/java/com/android/safetycenter/UserProfileGroup.java
@@ -129,9 +129,8 @@ public final class UserProfileGroup {
* is disabled.
*/
public static UserProfileGroup fromUser(Context context, @UserIdInt int userId) {
- Context userContext = UserUtils.getUserContext(userId, context);
- List<UserHandle> userProfiles = UserUtils.getUserProfiles(userContext);
- int profileParentUserId = UserUtils.getProfileParentIdOrSelf(userId, userContext);
+ List<UserHandle> userProfiles = UserUtils.getUserProfiles(userId, context);
+ int profileParentUserId = UserUtils.getProfileParentIdOrSelf(userId, context);
int[] managedProfilesUserIds = new int[userProfiles.size()];
int[] managedRunningProfilesUserIds = new int[userProfiles.size()];
diff --git a/tests/cts/permissionpolicy/res/raw/android_manifest.xml b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
index cd80fe78e..ceefe3dfd 100644
--- a/tests/cts/permissionpolicy/res/raw/android_manifest.xml
+++ b/tests/cts/permissionpolicy/res/raw/android_manifest.xml
@@ -7759,7 +7759,17 @@
@FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")
@hide -->
<permission android:name="android.permission.READ_BLOCKED_NUMBERS"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature"
+ android:featureFlag="!android.permission.flags.grant_read_blocked_numbers_to_system_ui_intelligence" />
+
+ <!-- Allows the holder to read blocked numbers. See
+ {@link android.provider.BlockedNumberContract}.
+ @SystemApi
+ @FlaggedApi("com.android.server.telecom.flags.telecom_resolve_hidden_dependencies")
+ @hide -->
+ <permission android:name="android.permission.READ_BLOCKED_NUMBERS"
+ android:protectionLevel="signature|role"
+ android:featureFlag="android.permission.flags.grant_read_blocked_numbers_to_system_ui_intelligence" />
<!-- Allows the holder to write blocked numbers. See
{@link android.provider.BlockedNumberContract}.
diff --git a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
index 751c56b3c..9a12765c0 100644
--- a/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
+++ b/tests/cts/permissionui/src/android/permissionui/cts/PermissionRationalePermissionGrantDialogTest.kt
@@ -41,8 +41,7 @@ import org.junit.Test
@FlakyTest
class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
- @get:Rule
- val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+ @get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@get:Rule
val deviceConfigPermissionRationaleEnabled =
@@ -50,7 +49,7 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
context,
DeviceConfig.NAMESPACE_PRIVACY,
PERMISSION_RATIONALE_ENABLED,
- true.toString()
+ true.toString(),
)
@Before
@@ -248,8 +247,10 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
- "VanillaIceCream")
+ @SdkSuppress(
+ minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream",
+ )
@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
@Test
fun requestCoarseLocationPerm_hasAslInApk_packageSourceUnspecified() {
@@ -262,8 +263,10 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
- "VanillaIceCream")
+ @SdkSuppress(
+ minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream",
+ )
@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
@Test
fun requestCoarseLocationPerm_hasAslInApk_packageSourceStore() {
@@ -276,8 +279,10 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
- "VanillaIceCream")
+ @SdkSuppress(
+ minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream",
+ )
@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
@Test
fun requestCoarseLocationPerm_hasAslInApk_packageSourceLocalFile() {
@@ -290,8 +295,10 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
- "VanillaIceCream")
+ @SdkSuppress(
+ minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream",
+ )
@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
@Test
fun requestCoarseLocationPerm_hasAslInApk_packageSourceDownloadedFile() {
@@ -304,8 +311,10 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
}
}
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, codeName =
- "VanillaIceCream")
+ @SdkSuppress(
+ minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM,
+ codeName = "VanillaIceCream",
+ )
@RequiresFlagsEnabled(android.content.pm.Flags.FLAG_ASL_IN_APK_APP_METADATA_SOURCE)
@Test
fun requestCoarseLocationPerm_hasAslInApk_packageSourceOther() {
@@ -338,7 +347,6 @@ class PermissionRationalePermissionGrantDialogTest : BaseUsePermissionTest() {
requestAppPermissionsForNoResult(ACCESS_FINE_LOCATION) {
clickPermissionRationaleViewInGrantDialog()
assertPermissionRationaleDialogIsVisible(true)
- assertPermissionRationaleContainerOnGrantDialogIsVisible(false)
}
}
diff --git a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt
index 98aa5fbf1..f070fa9aa 100644
--- a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt
+++ b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt
@@ -31,6 +31,7 @@ import android.util.Pair
import androidx.test.filters.SdkSuppress
import androidx.test.rule.ActivityTestRule
import androidx.test.uiautomator.By
+import com.android.bedstead.enterprise.annotations.EnsureDoesNotHaveUserRestriction
import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile
import com.android.bedstead.enterprise.annotations.EnsureHasUserRestriction
import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile
@@ -53,6 +54,7 @@ import com.android.bedstead.nene.TestApis.context
import com.android.bedstead.nene.TestApis.permissions
import com.android.bedstead.nene.TestApis.users
import com.android.bedstead.nene.types.OptionalBoolean
+import com.android.bedstead.nene.userrestrictions.CommonUserRestrictions.DISALLOW_ADD_MANAGED_PROFILE
import com.android.bedstead.nene.users.UserReference
import com.android.bedstead.nene.users.UserType
import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL
@@ -69,7 +71,6 @@ import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObjectOrNull
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
-import java.util.Objects
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
@@ -315,7 +316,7 @@ class RoleManagerMultiUserTest {
// initialUser needs to be not the targetUser
val targetActiveUser = users().current().userHandle()
val initialUser =
- if (Objects.equals(targetActiveUser, deviceState.initialUser().userHandle())) {
+ if (targetActiveUser == deviceState.initialUser().userHandle()) {
deviceState.workProfile().userHandle()
} else {
deviceState.initialUser().userHandle()
@@ -570,6 +571,7 @@ class RoleManagerMultiUserTest {
@EnsureCanAddUser
@EnsureHasNoWorkProfile
@RequireRunOnPrimaryUser
+ @EnsureDoesNotHaveUserRestriction(DISALLOW_ADD_MANAGED_PROFILE)
@Test
@Throws(Exception::class)
fun ensureActiveUserSetToParentOnUserRemoved() {
@@ -1645,7 +1647,12 @@ class RoleManagerMultiUserTest {
getUiDevice().waitForIdle()
// CollapsingToolbar title can't be found by text, so using description instead.
- assertNull(waitFindObjectOrNull(By.desc(PROFILE_GROUP_EXCLUSIVITY_ROLE_LABEL)))
+ assertNull(
+ waitFindObjectOrNull(
+ By.desc(PROFILE_GROUP_EXCLUSIVITY_ROLE_LABEL),
+ IDLE_TIMEOUT_MILLIS,
+ )
+ )
pressBack()
pressBack()
@@ -1681,7 +1688,12 @@ class RoleManagerMultiUserTest {
getUiDevice().waitForIdle()
// CollapsingToolbar title can't be found by text, so using description instead.
- assertNull(waitFindObjectOrNull(By.desc(PROFILE_GROUP_EXCLUSIVITY_ROLE_LABEL)))
+ assertNull(
+ waitFindObjectOrNull(
+ By.desc(PROFILE_GROUP_EXCLUSIVITY_ROLE_LABEL),
+ IDLE_TIMEOUT_MILLIS,
+ )
+ )
pressBack()
pressBack()
@@ -1816,7 +1828,8 @@ class RoleManagerMultiUserTest {
if (isWatch) {
assertNull(
waitFindObjectOrNull(
- By.clickable(true).checked(true).hasDescendant(By.text(targetAppLabel))
+ By.clickable(true).checked(true).hasDescendant(By.text(targetAppLabel)),
+ IDLE_TIMEOUT_MILLIS,
)
)
} else {
@@ -1824,7 +1837,8 @@ class RoleManagerMultiUserTest {
waitFindObjectOrNull(
By.clickable(true)
.hasDescendant(By.checkable(true).checked(true))
- .hasDescendant(By.text(targetAppLabel))
+ .hasDescendant(By.text(targetAppLabel)),
+ IDLE_TIMEOUT_MILLIS,
)
)
}
@@ -1895,7 +1909,8 @@ class RoleManagerMultiUserTest {
if (isWatch) {
assertNull(
waitFindObjectOrNull(
- By.clickable(true).checked(true).hasDescendant(By.text(targetAppLabel))
+ By.clickable(true).checked(true).hasDescendant(By.text(targetAppLabel)),
+ IDLE_TIMEOUT_MILLIS,
)
)
} else {
@@ -1903,7 +1918,8 @@ class RoleManagerMultiUserTest {
waitFindObjectOrNull(
By.clickable(true)
.hasDescendant(By.checkable(true).checked(true))
- .hasDescendant(By.text(targetAppLabel))
+ .hasDescendant(By.text(targetAppLabel)),
+ IDLE_TIMEOUT_MILLIS,
)
)
}
@@ -2069,10 +2085,8 @@ class RoleManagerMultiUserTest {
}
}
- @Throws(java.lang.Exception::class)
private fun installAppForAllUsers() {
SystemUtil.runShellCommandOrThrow("pm install -r --user all $APP_APK_PATH")
- SystemUtil.waitForBroadcasts()
}
private fun uninstallAppForAllUsers() {
@@ -2099,8 +2113,7 @@ class RoleManagerMultiUserTest {
}
val result: Pair<Int, Intent?> = clickButtonAndWaitForResult(allow)
val expectedResult =
- if (allow && Objects.equals(targetActiveUser, users().instrumented().userHandle()))
- Activity.RESULT_OK
+ if (allow && targetActiveUser == users().instrumented().userHandle()) Activity.RESULT_OK
else Activity.RESULT_CANCELED
assertThat(result.first).isEqualTo(expectedResult)
@@ -2118,7 +2131,8 @@ class RoleManagerMultiUserTest {
}
private fun roleRequestNotShown() {
- val requestRoleItem = waitFindObjectOrNull(By.textStartsWith(APP_LABEL))
+ val requestRoleItem =
+ waitFindObjectOrNull(By.textStartsWith(APP_LABEL), IDLE_TIMEOUT_MILLIS)
assertNull(requestRoleItem)
val result: Pair<Int, Intent?> = waitForResult()
@@ -2148,9 +2162,9 @@ class RoleManagerMultiUserTest {
) {
for (userReference in users().profileGroup(deviceState.initialUser())) {
val user = userReference.userHandle()
- if (Objects.equals(user, expectedActiveUser)) {
- val roleHolders =
- roleManager.getRoleHoldersAsUser(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, user)
+ val roleHolders =
+ roleManager.getRoleHoldersAsUser(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, user)
+ if (user == expectedActiveUser) {
assertWithMessage(
"Expected user ${user.identifier} to have a role holder for " +
" $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME"
@@ -2169,9 +2183,7 @@ class RoleManagerMultiUserTest {
"Expected user ${user.identifier} to not have a role holder for" +
" $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME"
)
- .that(
- roleManager.getRoleHoldersAsUser(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, user)
- )
+ .that(roleHolders)
.isEmpty()
}
}
@@ -2183,7 +2195,7 @@ class RoleManagerMultiUserTest {
for (userReference in users().profileGroup(deviceState.initialUser())) {
val userRoleManager = getRoleManagerForUser(userReference)
val user = userReference.userHandle()
- if (Objects.equals(user, expectedActiveUser)) {
+ if (user == expectedActiveUser) {
assertWithMessage("Expected default application for user ${user.identifier}")
.that(
userRoleManager.getDefaultApplication(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)
@@ -2251,6 +2263,7 @@ class RoleManagerMultiUserTest {
companion object {
private const val TIMEOUT_MILLIS: Long = (15 * 1000).toLong()
+ private const val IDLE_TIMEOUT_MILLIS: Long = (2 * 1000).toLong()
private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME =
RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY
private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_LABEL =
diff --git a/tests/cts/safetycenter/AndroidTest.xml b/tests/cts/safetycenter/AndroidTest.xml
index 6d8c3069c..ed161f0b6 100644
--- a/tests/cts/safetycenter/AndroidTest.xml
+++ b/tests/cts/safetycenter/AndroidTest.xml
@@ -47,6 +47,10 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
diff --git a/tests/functional/safetycenter/multiusers/AndroidTest.xml b/tests/functional/safetycenter/multiusers/AndroidTest.xml
index 20032357a..bfb7fdbf2 100644
--- a/tests/functional/safetycenter/multiusers/AndroidTest.xml
+++ b/tests/functional/safetycenter/multiusers/AndroidTest.xml
@@ -47,6 +47,10 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
diff --git a/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml b/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
index a1826653f..ee79dcd2a 100644
--- a/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
+++ b/tests/functional/safetycenter/safetycenteractivity/AndroidTest.xml
@@ -47,6 +47,10 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
diff --git a/tests/functional/safetycenter/singleuser/AndroidTest.xml b/tests/functional/safetycenter/singleuser/AndroidTest.xml
index af040eb6f..f778ca93e 100644
--- a/tests/functional/safetycenter/singleuser/AndroidTest.xml
+++ b/tests/functional/safetycenter/singleuser/AndroidTest.xml
@@ -47,8 +47,8 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
- <!-- TODO(b/379928062): Ensure device not on lockscreen. Reassess when keyguard bug is
- closed -->
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
<option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
<option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
diff --git a/tests/functional/safetycenter/subpages/AndroidTest.xml b/tests/functional/safetycenter/subpages/AndroidTest.xml
index c3245e9d7..ac493841f 100644
--- a/tests/functional/safetycenter/subpages/AndroidTest.xml
+++ b/tests/functional/safetycenter/subpages/AndroidTest.xml
@@ -47,6 +47,10 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>
diff --git a/tests/hostside/safetycenter/AndroidTest.xml b/tests/hostside/safetycenter/AndroidTest.xml
index a28b70c3c..41f0bcc40 100644
--- a/tests/hostside/safetycenter/AndroidTest.xml
+++ b/tests/hostside/safetycenter/AndroidTest.xml
@@ -32,6 +32,10 @@
<!-- Disable syncing to prevent overwriting flags during testing. -->
<option name="run-command" value="device_config set_sync_disabled_for_tests persistent" />
<option name="teardown-command" value="device_config set_sync_disabled_for_tests none" />
+ <!-- Belt-and-braces attempt to dismiss keyguard. Tradefed should have already done this
+ for us, but this is a precaution in an attempt to mitigate b/379620557. -->
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
<!-- Dismiss any system dialogs (e.g. crashes, ANR). -->
<option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS --receiver-foreground" />
</target_preparer>